Initial Grease Pencil 3.0 stage #106848
|
@ -645,7 +645,7 @@ if(WITH_GHOST_WAYLAND)
|
|||
else()
|
||||
# Rocky8 packages have too old a version, a newer version exist in the pre-compiled libraries.
|
||||
find_path(WAYLAND_PROTOCOLS_DIR
|
||||
NAMES unstable/xdg-decoration/xdg-decoration-unstable-v1.xml
|
||||
NAMES staging/xdg-activation/xdg-activation-v1.xml
|
||||
PATH_SUFFIXES share/wayland-protocols
|
||||
PATHS ${LIBDIR}/wayland-protocols
|
||||
)
|
||||
|
|
|
@ -590,11 +590,10 @@ bool MetalDeviceQueue::enqueue(DeviceKernel kernel,
|
|||
[mtlComputeCommandEncoder setThreadgroupMemoryLength:shared_mem_bytes atIndex:0];
|
||||
}
|
||||
|
||||
MTLSize size_threadgroups_per_dispatch = MTLSizeMake(
|
||||
divide_up(work_size, num_threads_per_block), 1, 1);
|
||||
MTLSize size_threads_per_dispatch = MTLSizeMake(work_size, 1, 1);
|
||||
MTLSize size_threads_per_threadgroup = MTLSizeMake(num_threads_per_block, 1, 1);
|
||||
[mtlComputeCommandEncoder dispatchThreadgroups:size_threadgroups_per_dispatch
|
||||
threadsPerThreadgroup:size_threads_per_threadgroup];
|
||||
[mtlComputeCommandEncoder dispatchThreads:size_threads_per_dispatch
|
||||
threadsPerThreadgroup:size_threads_per_threadgroup];
|
||||
|
||||
[mtlCommandBuffer_ addCompletedHandler:^(id<MTLCommandBuffer> command_buffer) {
|
||||
NSString *kernel_name = metal_kernel_pso->function.label;
|
||||
|
|
|
@ -91,6 +91,7 @@
|
|||
#define ccl_gpu_kernel_postfix
|
||||
|
||||
#define ccl_gpu_kernel_call(x) x
|
||||
#define ccl_gpu_kernel_within_bounds(i, n) ((i) < (n))
|
||||
|
||||
/* Define a function object where "func" is the lambda body, and additional parameters are used to
|
||||
* specify captured state */
|
||||
|
|
|
@ -136,7 +136,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
|
|||
{
|
||||
const int global_index = ccl_gpu_global_id_x();
|
||||
|
||||
if (global_index < work_size) {
|
||||
if (ccl_gpu_kernel_within_bounds(global_index, work_size)) {
|
||||
const int state = (path_index_array) ? path_index_array[global_index] : global_index;
|
||||
ccl_gpu_kernel_call(integrator_intersect_closest(NULL, state, render_buffer));
|
||||
}
|
||||
|
@ -150,7 +150,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
|
|||
{
|
||||
const int global_index = ccl_gpu_global_id_x();
|
||||
|
||||
if (global_index < work_size) {
|
||||
if (ccl_gpu_kernel_within_bounds(global_index, work_size)) {
|
||||
const int state = (path_index_array) ? path_index_array[global_index] : global_index;
|
||||
ccl_gpu_kernel_call(integrator_intersect_shadow(NULL, state));
|
||||
}
|
||||
|
@ -164,7 +164,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
|
|||
{
|
||||
const int global_index = ccl_gpu_global_id_x();
|
||||
|
||||
if (global_index < work_size) {
|
||||
if (ccl_gpu_kernel_within_bounds(global_index, work_size)) {
|
||||
const int state = (path_index_array) ? path_index_array[global_index] : global_index;
|
||||
ccl_gpu_kernel_call(integrator_intersect_subsurface(NULL, state));
|
||||
}
|
||||
|
@ -178,7 +178,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
|
|||
{
|
||||
const int global_index = ccl_gpu_global_id_x();
|
||||
|
||||
if (global_index < work_size) {
|
||||
if (ccl_gpu_kernel_within_bounds(global_index, work_size)) {
|
||||
const int state = (path_index_array) ? path_index_array[global_index] : global_index;
|
||||
ccl_gpu_kernel_call(integrator_intersect_volume_stack(NULL, state));
|
||||
}
|
||||
|
@ -193,7 +193,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
|
|||
{
|
||||
const int global_index = ccl_gpu_global_id_x();
|
||||
|
||||
if (global_index < work_size) {
|
||||
if (ccl_gpu_kernel_within_bounds(global_index, work_size)) {
|
||||
const int state = (path_index_array) ? path_index_array[global_index] : global_index;
|
||||
ccl_gpu_kernel_call(integrator_shade_background(NULL, state, render_buffer));
|
||||
}
|
||||
|
@ -208,7 +208,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
|
|||
{
|
||||
const int global_index = ccl_gpu_global_id_x();
|
||||
|
||||
if (global_index < work_size) {
|
||||
if (ccl_gpu_kernel_within_bounds(global_index, work_size)) {
|
||||
const int state = (path_index_array) ? path_index_array[global_index] : global_index;
|
||||
ccl_gpu_kernel_call(integrator_shade_light(NULL, state, render_buffer));
|
||||
}
|
||||
|
@ -223,7 +223,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
|
|||
{
|
||||
const int global_index = ccl_gpu_global_id_x();
|
||||
|
||||
if (global_index < work_size) {
|
||||
if (ccl_gpu_kernel_within_bounds(global_index, work_size)) {
|
||||
const int state = (path_index_array) ? path_index_array[global_index] : global_index;
|
||||
ccl_gpu_kernel_call(integrator_shade_shadow(NULL, state, render_buffer));
|
||||
}
|
||||
|
@ -238,7 +238,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
|
|||
{
|
||||
const int global_index = ccl_gpu_global_id_x();
|
||||
|
||||
if (global_index < work_size) {
|
||||
if (ccl_gpu_kernel_within_bounds(global_index, work_size)) {
|
||||
const int state = (path_index_array) ? path_index_array[global_index] : global_index;
|
||||
ccl_gpu_kernel_call(integrator_shade_surface(NULL, state, render_buffer));
|
||||
}
|
||||
|
@ -257,7 +257,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
|
|||
{
|
||||
const int global_index = ccl_gpu_global_id_x();
|
||||
|
||||
if (global_index < work_size) {
|
||||
if (ccl_gpu_kernel_within_bounds(global_index, work_size)) {
|
||||
const int state = (path_index_array) ? path_index_array[global_index] : global_index;
|
||||
|
||||
#if defined(__KERNEL_METAL_APPLE__) && defined(__METALRT__)
|
||||
|
@ -281,7 +281,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
|
|||
{
|
||||
const int global_index = ccl_gpu_global_id_x();
|
||||
|
||||
if (global_index < work_size) {
|
||||
if (ccl_gpu_kernel_within_bounds(global_index, work_size)) {
|
||||
const int state = (path_index_array) ? path_index_array[global_index] : global_index;
|
||||
ccl_gpu_kernel_call(integrator_shade_surface_mnee(NULL, state, render_buffer));
|
||||
}
|
||||
|
@ -296,7 +296,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
|
|||
{
|
||||
const int global_index = ccl_gpu_global_id_x();
|
||||
|
||||
if (global_index < work_size) {
|
||||
if (ccl_gpu_kernel_within_bounds(global_index, work_size)) {
|
||||
const int state = (path_index_array) ? path_index_array[global_index] : global_index;
|
||||
ccl_gpu_kernel_call(integrator_shade_volume(NULL, state, render_buffer));
|
||||
}
|
||||
|
@ -492,7 +492,7 @@ ccl_gpu_kernel_threads(GPU_PARALLEL_SORTED_INDEX_DEFAULT_BLOCK_SIZE)
|
|||
{
|
||||
const int global_index = ccl_gpu_global_id_x();
|
||||
|
||||
if (global_index < work_size) {
|
||||
if (ccl_gpu_kernel_within_bounds(global_index, work_size)) {
|
||||
const int from_state = active_terminated_states[active_states_offset + global_index];
|
||||
const int to_state = active_terminated_states[terminated_states_offset + global_index];
|
||||
|
||||
|
@ -526,7 +526,7 @@ ccl_gpu_kernel_threads(GPU_PARALLEL_SORTED_INDEX_DEFAULT_BLOCK_SIZE)
|
|||
{
|
||||
const int global_index = ccl_gpu_global_id_x();
|
||||
|
||||
if (global_index < work_size) {
|
||||
if (ccl_gpu_kernel_within_bounds(global_index, work_size)) {
|
||||
const int from_state = active_terminated_states[active_states_offset + global_index];
|
||||
const int to_state = active_terminated_states[terminated_states_offset + global_index];
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#define ccl_gpu_kernel_postfix
|
||||
|
||||
#define ccl_gpu_kernel_call(x) x
|
||||
#define ccl_gpu_kernel_within_bounds(i, n) ((i) < (n))
|
||||
|
||||
/* Define a function object where "func" is the lambda body, and additional parameters are used to
|
||||
* specify captured state */
|
||||
|
|
|
@ -143,6 +143,7 @@ void kernel_gpu_##name::run(thread MetalKernelContext& context, \
|
|||
|
||||
#define ccl_gpu_kernel_postfix
|
||||
#define ccl_gpu_kernel_call(x) context.x
|
||||
#define ccl_gpu_kernel_within_bounds(i,n) true
|
||||
|
||||
/* define a function object where "func" is the lambda body, and additional parameters are used to specify captured state */
|
||||
#define ccl_gpu_kernel_lambda(func, ...) \
|
||||
|
|
|
@ -289,9 +289,8 @@ bool metalrt_shadow_all_hit(constant KernelParamsMetal &launch_params_metal,
|
|||
}
|
||||
|
||||
if (ray_tmax >= max_recorded_t) {
|
||||
/* Accept hit, so that we don't consider any more hits beyond the distance of the
|
||||
* current hit anymore. */
|
||||
payload.result = true;
|
||||
/* Ray hits are not guaranteed to be ordered by distance so don't exit early here.
|
||||
* Continue search. */
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -101,6 +101,7 @@ void oneapi_kernel_##name(KernelGlobalsGPU *ccl_restrict kg, \
|
|||
#endif
|
||||
|
||||
#define ccl_gpu_kernel_call(x) ((ONEAPIKernelContext*)kg)->x
|
||||
#define ccl_gpu_kernel_within_bounds(i, n) ((i) < (n))
|
||||
|
||||
#define ccl_gpu_kernel_lambda(func, ...) \
|
||||
struct KernelLambda \
|
||||
|
|
|
@ -205,6 +205,14 @@ static bool use_gnome_confine_hack = false;
|
|||
|
||||
#define WL_NAME_UNSET uint32_t(-1)
|
||||
|
||||
/**
|
||||
* Initializer for GHOST integer coordinates from `wl_fixed_t`,
|
||||
* taking window scale into account.
|
||||
*/
|
||||
#define WL_FIXED_TO_INT_FOR_WINDOW_V2(win, xy) \
|
||||
wl_fixed_to_int((win)->wl_fixed_to_window((xy)[0])), \
|
||||
wl_fixed_to_int((win)->wl_fixed_to_window((xy)[1])),
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
@ -1925,8 +1933,6 @@ static void relative_pointer_handle_relative_motion_impl(GWL_Seat *seat,
|
|||
GHOST_WindowWayland *win,
|
||||
const wl_fixed_t xy[2])
|
||||
{
|
||||
const wl_fixed_t scale = win->scale();
|
||||
|
||||
seat->pointer.xy[0] = xy[0];
|
||||
seat->pointer.xy[1] = xy[1];
|
||||
|
||||
|
@ -1937,21 +1943,19 @@ static void relative_pointer_handle_relative_motion_impl(GWL_Seat *seat,
|
|||
/* Needed or the cursor is considered outside the window and doesn't restore the location. */
|
||||
bounds.m_r -= 1;
|
||||
bounds.m_b -= 1;
|
||||
|
||||
bounds.m_l = wl_fixed_from_int(bounds.m_l) / scale;
|
||||
bounds.m_t = wl_fixed_from_int(bounds.m_t) / scale;
|
||||
bounds.m_r = wl_fixed_from_int(bounds.m_r) / scale;
|
||||
bounds.m_b = wl_fixed_from_int(bounds.m_b) / scale;
|
||||
bounds.m_l = win->wl_fixed_from_window(wl_fixed_from_int(bounds.m_l));
|
||||
bounds.m_t = win->wl_fixed_from_window(wl_fixed_from_int(bounds.m_t));
|
||||
bounds.m_r = win->wl_fixed_from_window(wl_fixed_from_int(bounds.m_r));
|
||||
bounds.m_b = win->wl_fixed_from_window(wl_fixed_from_int(bounds.m_b));
|
||||
bounds.clampPoint(UNPACK2(seat->pointer.xy));
|
||||
}
|
||||
#endif
|
||||
seat->system->pushEvent_maybe_pending(
|
||||
new GHOST_EventCursor(seat->system->getMilliSeconds(),
|
||||
GHOST_kEventCursorMove,
|
||||
win,
|
||||
wl_fixed_to_int(scale * seat->pointer.xy[0]),
|
||||
wl_fixed_to_int(scale * seat->pointer.xy[1]),
|
||||
GHOST_TABLET_DATA_NONE));
|
||||
const int event_xy[2] = {WL_FIXED_TO_INT_FOR_WINDOW_V2(win, seat->pointer.xy)};
|
||||
seat->system->pushEvent_maybe_pending(new GHOST_EventCursor(seat->system->getMilliSeconds(),
|
||||
GHOST_kEventCursorMove,
|
||||
win,
|
||||
UNPACK2(event_xy),
|
||||
GHOST_TABLET_DATA_NONE));
|
||||
}
|
||||
|
||||
static void relative_pointer_handle_relative_motion(
|
||||
|
@ -1968,10 +1972,9 @@ static void relative_pointer_handle_relative_motion(
|
|||
if (wl_surface *wl_surface_focus = seat->pointer.wl_surface_window) {
|
||||
CLOG_INFO(LOG, 2, "relative_motion");
|
||||
GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus);
|
||||
const wl_fixed_t scale = win->scale();
|
||||
const wl_fixed_t xy_next[2] = {
|
||||
seat->pointer.xy[0] + (dx / scale),
|
||||
seat->pointer.xy[1] + (dy / scale),
|
||||
seat->pointer.xy[0] + win->wl_fixed_from_window(dx),
|
||||
seat->pointer.xy[1] + win->wl_fixed_from_window(dy),
|
||||
};
|
||||
relative_pointer_handle_relative_motion_impl(seat, win, xy_next);
|
||||
}
|
||||
|
@ -2000,12 +2003,7 @@ static void dnd_events(const GWL_Seat *const seat, const GHOST_TEventType event)
|
|||
/* NOTE: `seat->data_offer_dnd_mutex` must already be locked. */
|
||||
if (wl_surface *wl_surface_focus = seat->wl_surface_window_focus_dnd) {
|
||||
GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus);
|
||||
const wl_fixed_t scale = win->scale();
|
||||
const int event_xy[2] = {
|
||||
wl_fixed_to_int(scale * seat->data_offer_dnd->dnd.xy[0]),
|
||||
wl_fixed_to_int(scale * seat->data_offer_dnd->dnd.xy[1]),
|
||||
};
|
||||
|
||||
const int event_xy[2] = {WL_FIXED_TO_INT_FOR_WINDOW_V2(win, seat->data_offer_dnd->dnd.xy)};
|
||||
const uint64_t time = seat->system->getMilliSeconds();
|
||||
for (size_t i = 0; i < ARRAY_SIZE(ghost_wl_mime_preference_order_type); i++) {
|
||||
const GHOST_TDragnDropTypes type = ghost_wl_mime_preference_order_type[i];
|
||||
|
@ -2477,13 +2475,12 @@ static void data_device_handle_drop(void *data, struct wl_data_device * /*wl_dat
|
|||
}
|
||||
|
||||
CLOG_INFO(LOG, 2, "drop_read_uris_fn file_count=%d", flist->count);
|
||||
const wl_fixed_t scale = win->scale();
|
||||
const int event_xy[2] = {WL_FIXED_TO_INT_FOR_WINDOW_V2(win, xy)};
|
||||
system->pushEvent_maybe_pending(new GHOST_EventDragnDrop(system->getMilliSeconds(),
|
||||
GHOST_kEventDraggingDropDone,
|
||||
GHOST_kDragnDropTypeFilenames,
|
||||
win,
|
||||
wl_fixed_to_int(scale * xy[0]),
|
||||
wl_fixed_to_int(scale * xy[1]),
|
||||
UNPACK2(event_xy),
|
||||
flist));
|
||||
}
|
||||
else if (ELEM(mime_receive, ghost_wl_mime_text_plain, ghost_wl_mime_text_utf8)) {
|
||||
|
@ -2685,14 +2682,12 @@ static void pointer_handle_enter(void *data,
|
|||
|
||||
seat->system->cursor_shape_set(win->getCursorShape());
|
||||
|
||||
const wl_fixed_t scale = win->scale();
|
||||
seat->system->pushEvent_maybe_pending(
|
||||
new GHOST_EventCursor(seat->system->getMilliSeconds(),
|
||||
GHOST_kEventCursorMove,
|
||||
win,
|
||||
wl_fixed_to_int(scale * seat->pointer.xy[0]),
|
||||
wl_fixed_to_int(scale * seat->pointer.xy[1]),
|
||||
GHOST_TABLET_DATA_NONE));
|
||||
const int event_xy[2] = {WL_FIXED_TO_INT_FOR_WINDOW_V2(win, seat->pointer.xy)};
|
||||
seat->system->pushEvent_maybe_pending(new GHOST_EventCursor(seat->system->getMilliSeconds(),
|
||||
GHOST_kEventCursorMove,
|
||||
win,
|
||||
UNPACK2(event_xy),
|
||||
GHOST_TABLET_DATA_NONE));
|
||||
}
|
||||
|
||||
static void pointer_handle_leave(void *data,
|
||||
|
@ -2723,14 +2718,12 @@ static void pointer_handle_motion(void *data,
|
|||
if (wl_surface *wl_surface_focus = seat->pointer.wl_surface_window) {
|
||||
CLOG_INFO(LOG, 2, "motion");
|
||||
GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus);
|
||||
const wl_fixed_t scale = win->scale();
|
||||
seat->system->pushEvent_maybe_pending(
|
||||
new GHOST_EventCursor(seat->system->getMilliSeconds(),
|
||||
GHOST_kEventCursorMove,
|
||||
win,
|
||||
wl_fixed_to_int(scale * seat->pointer.xy[0]),
|
||||
wl_fixed_to_int(scale * seat->pointer.xy[1]),
|
||||
GHOST_TABLET_DATA_NONE));
|
||||
const int event_xy[2] = {WL_FIXED_TO_INT_FOR_WINDOW_V2(win, seat->pointer.xy)};
|
||||
seat->system->pushEvent_maybe_pending(new GHOST_EventCursor(seat->system->getMilliSeconds(),
|
||||
GHOST_kEventCursorMove,
|
||||
win,
|
||||
UNPACK2(event_xy),
|
||||
GHOST_TABLET_DATA_NONE));
|
||||
}
|
||||
else {
|
||||
CLOG_INFO(LOG, 2, "motion (skipped)");
|
||||
|
@ -2849,13 +2842,12 @@ static void pointer_handle_frame(void *data, struct wl_pointer * /*wl_pointer*/)
|
|||
if (seat->pointer_scroll.smooth_xy[0] || seat->pointer_scroll.smooth_xy[1]) {
|
||||
if (wl_surface *wl_surface_focus = seat->pointer.wl_surface_window) {
|
||||
GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus);
|
||||
const wl_fixed_t scale = win->scale();
|
||||
const int event_xy[2] = {WL_FIXED_TO_INT_FOR_WINDOW_V2(win, seat->pointer.xy)};
|
||||
seat->system->pushEvent_maybe_pending(new GHOST_EventTrackpad(
|
||||
seat->system->getMilliSeconds(),
|
||||
win,
|
||||
GHOST_kTrackpadEventScroll,
|
||||
wl_fixed_to_int(scale * seat->pointer.xy[0]),
|
||||
wl_fixed_to_int(scale * seat->pointer.xy[1]),
|
||||
UNPACK2(event_xy),
|
||||
/* NOTE: scaling the delta doesn't seem necessary.
|
||||
* NOTE: inverting delta gives correct results, see: QTBUG-85767.
|
||||
* NOTE: the preference to invert scrolling (in GNOME at least)
|
||||
|
@ -3082,11 +3074,7 @@ static void gesture_pinch_handle_update(void *data,
|
|||
&seat->pointer_gesture_pinch.rotation, rotation);
|
||||
|
||||
if (win) {
|
||||
const wl_fixed_t win_scale = win->scale();
|
||||
const int32_t event_xy[2] = {
|
||||
wl_fixed_to_int(win_scale * seat->pointer.xy[0]),
|
||||
wl_fixed_to_int(win_scale * seat->pointer.xy[1]),
|
||||
};
|
||||
const int event_xy[2] = {WL_FIXED_TO_INT_FOR_WINDOW_V2(win, seat->pointer.xy)};
|
||||
if (scale_as_delta_px) {
|
||||
seat->system->pushEvent_maybe_pending(
|
||||
new GHOST_EventTrackpad(seat->system->getMilliSeconds(),
|
||||
|
@ -3566,14 +3554,12 @@ static void tablet_tool_handle_frame(void *data,
|
|||
/* No need to check the surfaces origin, it's already known to be owned by GHOST. */
|
||||
if (wl_surface *wl_surface_focus = seat->tablet.wl_surface_window) {
|
||||
GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus);
|
||||
const wl_fixed_t scale = win->scale();
|
||||
seat->system->pushEvent_maybe_pending(
|
||||
new GHOST_EventCursor(seat->system->getMilliSeconds(),
|
||||
GHOST_kEventCursorMove,
|
||||
win,
|
||||
wl_fixed_to_int(scale * seat->tablet.xy[0]),
|
||||
wl_fixed_to_int(scale * seat->tablet.xy[1]),
|
||||
tablet_tool->data));
|
||||
const int event_xy[2] = {WL_FIXED_TO_INT_FOR_WINDOW_V2(win, seat->tablet.xy)};
|
||||
seat->system->pushEvent_maybe_pending(new GHOST_EventCursor(seat->system->getMilliSeconds(),
|
||||
GHOST_kEventCursorMove,
|
||||
win,
|
||||
UNPACK2(event_xy),
|
||||
tablet_tool->data));
|
||||
if (tablet_tool->proximity == false) {
|
||||
seat->system->cursor_shape_set(win->getCursorShape());
|
||||
}
|
||||
|
@ -6020,7 +6006,6 @@ static GHOST_TSuccess getCursorPositionClientRelative_impl(
|
|||
int32_t &x,
|
||||
int32_t &y)
|
||||
{
|
||||
const wl_fixed_t scale = win->scale();
|
||||
|
||||
if (win->getCursorGrabModeIsWarp()) {
|
||||
/* As the cursor is restored at the warped location,
|
||||
|
@ -6037,18 +6022,19 @@ static GHOST_TSuccess getCursorPositionClientRelative_impl(
|
|||
};
|
||||
|
||||
GHOST_Rect wrap_bounds_scale;
|
||||
wrap_bounds_scale.m_l = wl_fixed_from_int(wrap_bounds.m_l) / scale;
|
||||
wrap_bounds_scale.m_t = wl_fixed_from_int(wrap_bounds.m_t) / scale;
|
||||
wrap_bounds_scale.m_r = wl_fixed_from_int(wrap_bounds.m_r) / scale;
|
||||
wrap_bounds_scale.m_b = wl_fixed_from_int(wrap_bounds.m_b) / scale;
|
||||
|
||||
wrap_bounds_scale.m_l = win->wl_fixed_from_window(wl_fixed_from_int(wrap_bounds.m_l));
|
||||
wrap_bounds_scale.m_t = win->wl_fixed_from_window(wl_fixed_from_int(wrap_bounds.m_t));
|
||||
wrap_bounds_scale.m_r = win->wl_fixed_from_window(wl_fixed_from_int(wrap_bounds.m_r));
|
||||
wrap_bounds_scale.m_b = win->wl_fixed_from_window(wl_fixed_from_int(wrap_bounds.m_b));
|
||||
wrap_bounds_scale.wrapPoint(UNPACK2(xy_wrap), 0, win->getCursorGrabAxis());
|
||||
|
||||
x = wl_fixed_to_int(scale * xy_wrap[0]);
|
||||
y = wl_fixed_to_int(scale * xy_wrap[1]);
|
||||
x = wl_fixed_to_int(win->wl_fixed_to_window(xy_wrap[0]));
|
||||
y = wl_fixed_to_int(win->wl_fixed_to_window(xy_wrap[1]));
|
||||
}
|
||||
else {
|
||||
x = wl_fixed_to_int(scale * seat_state_pointer->xy[0]);
|
||||
y = wl_fixed_to_int(scale * seat_state_pointer->xy[1]);
|
||||
x = win->wl_fixed_to_window(seat_state_pointer->xy[0]);
|
||||
y = win->wl_fixed_to_window(seat_state_pointer->xy[1]);
|
||||
}
|
||||
|
||||
return GHOST_kSuccess;
|
||||
|
@ -6065,10 +6051,9 @@ static GHOST_TSuccess setCursorPositionClientRelative_impl(GWL_Seat *seat,
|
|||
if (!seat->wp_relative_pointer) {
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
const wl_fixed_t scale = win->scale();
|
||||
const wl_fixed_t xy_next[2] = {
|
||||
wl_fixed_from_int(x) / scale,
|
||||
wl_fixed_from_int(y) / scale,
|
||||
const wl_fixed_t xy_next[2]{
|
||||
win->wl_fixed_from_window(wl_fixed_from_int(x)),
|
||||
win->wl_fixed_from_window(wl_fixed_from_int(y)),
|
||||
};
|
||||
|
||||
/* As the cursor was "warped" generate an event at the new location. */
|
||||
|
|
|
@ -87,6 +87,29 @@ static void gwl_xdg_decor_window_destroy(WGL_XDG_Decor_Window *decor)
|
|||
/** \name Internal #GWL_Window
|
||||
* \{ */
|
||||
|
||||
#ifdef USE_EVENT_BACKGROUND_THREAD
|
||||
|
||||
enum eGWL_PendingWindowActions {
|
||||
/**
|
||||
* The state of the window frame has changed, apply the state from #GWL_Window::frame_pending.
|
||||
*/
|
||||
PENDING_WINDOW_FRAME_CONFIGURE = 0,
|
||||
/** The EGL buffer must be resized to match #GWL_WindowFrame::size. */
|
||||
PENDING_EGL_WINDOW_RESIZE,
|
||||
# ifdef GHOST_OPENGL_ALPHA
|
||||
/** Draw an opaque region behind the window. */
|
||||
PENDING_OPAQUE_SET,
|
||||
# endif
|
||||
/**
|
||||
* The DPI for a monitor has changed or the monitors (outputs)
|
||||
* this window is visible on may have changed. Recalculate the windows scale.
|
||||
*/
|
||||
PENDING_OUTPUT_SCALE_UPDATE,
|
||||
};
|
||||
# define PENDING_NUM (PENDING_OUTPUT_SCALE_UPDATE + 1)
|
||||
|
||||
#endif /* USE_EVENT_BACKGROUND_THREAD */
|
||||
|
||||
struct GWL_WindowFrame {
|
||||
int32_t size[2] = {0, 0};
|
||||
bool is_maximised = false;
|
||||
|
@ -148,7 +171,7 @@ struct GWL_Window {
|
|||
* These pending actions can't be performed when WAYLAND handlers are running from a thread.
|
||||
* Postpone their execution until the main thread can handle them.
|
||||
*/
|
||||
std::atomic<bool> pending_actions[3];
|
||||
std::atomic<bool> pending_actions[PENDING_NUM];
|
||||
#endif /* USE_EVENT_BACKGROUND_THREAD */
|
||||
};
|
||||
|
||||
|
@ -366,25 +389,6 @@ static void gwl_window_frame_update_from_pending(GWL_Window *win);
|
|||
|
||||
#ifdef USE_EVENT_BACKGROUND_THREAD
|
||||
|
||||
enum eGWL_PendingWindowActions {
|
||||
/**
|
||||
* The state of the window frame has changed, apply the state from #GWL_Window::frame_pending.
|
||||
*/
|
||||
PENDING_WINDOW_FRAME_CONFIGURE = 0,
|
||||
/** The EGL buffer must be resized to match #GWL_WindowFrame::size. */
|
||||
PENDING_EGL_WINDOW_RESIZE,
|
||||
# ifdef GHOST_OPENGL_ALPHA
|
||||
/** Draw an opaque region behind the window. */
|
||||
PENDING_OPAQUE_SET,
|
||||
# endif
|
||||
/**
|
||||
* The DPI for a monitor has changed or the monitors (outputs)
|
||||
* this window is visible on may have changed. Recalculate the windows scale.
|
||||
*/
|
||||
PENDING_OUTPUT_SCALE_UPDATE,
|
||||
};
|
||||
# define PENDING_NUM (PENDING_OUTPUT_SCALE_UPDATE + 1)
|
||||
|
||||
static void gwl_window_pending_actions_tag(GWL_Window *win, enum eGWL_PendingWindowActions type)
|
||||
{
|
||||
win->pending_actions[int(type)].store(true);
|
||||
|
@ -1384,6 +1388,16 @@ wl_fixed_t GHOST_WindowWayland::scale_fractional() const
|
|||
return window_->scale_fractional;
|
||||
}
|
||||
|
||||
wl_fixed_t GHOST_WindowWayland::wl_fixed_from_window(wl_fixed_t value) const
|
||||
{
|
||||
return value / window_->scale;
|
||||
}
|
||||
|
||||
wl_fixed_t GHOST_WindowWayland::wl_fixed_to_window(wl_fixed_t value) const
|
||||
{
|
||||
return value * window_->scale;
|
||||
}
|
||||
|
||||
wl_surface *GHOST_WindowWayland::wl_surface() const
|
||||
{
|
||||
return window_->wl_surface;
|
||||
|
|
|
@ -144,6 +144,9 @@ class GHOST_WindowWayland : public GHOST_Window {
|
|||
struct wl_surface *wl_surface() const;
|
||||
const std::vector<GWL_Output *> &outputs();
|
||||
|
||||
wl_fixed_t wl_fixed_from_window(wl_fixed_t value) const;
|
||||
wl_fixed_t wl_fixed_to_window(wl_fixed_t value) const;
|
||||
|
||||
/* WAYLAND window-level functions. */
|
||||
|
||||
GHOST_TSuccess close();
|
||||
|
|
|
@ -34,15 +34,17 @@ typedef struct BoxPack {
|
|||
* There is no limit to the space boxes may take, only that they will be packed
|
||||
* tightly into the lower left hand corner (0,0)
|
||||
*
|
||||
* \param boxarray: a pre-allocated array of boxes.
|
||||
* \param box_array: a pre-allocated array of boxes.
|
||||
* only the 'box->x' and 'box->y' are set, 'box->w' and 'box->h' are used,
|
||||
* 'box->index' is not used at all, the only reason its there
|
||||
* is that the box array is sorted by area and programs need to be able
|
||||
* to have some way of writing the boxes back to the original data.
|
||||
* \param len: the number of boxes in the array.
|
||||
* \param sort_boxes: Sort `box_array` before packing.
|
||||
* \param r_tot_x, r_tot_y: set so you can normalize the data.
|
||||
*/
|
||||
void BLI_box_pack_2d(BoxPack *boxarray, unsigned int len, float *r_tot_x, float *r_tot_y);
|
||||
void BLI_box_pack_2d(
|
||||
BoxPack *box_array, unsigned int len, bool sort_boxes, float *r_tot_x, float *r_tot_y);
|
||||
|
||||
typedef struct FixedSizeBoxPack {
|
||||
struct FixedSizeBoxPack *next, *prev;
|
||||
|
|
|
@ -266,7 +266,8 @@ static int vertex_sort(const void *p1, const void *p2, void *vs_ctx_p)
|
|||
|
||||
/** \} */
|
||||
|
||||
void BLI_box_pack_2d(BoxPack *boxarray, const uint len, float *r_tot_x, float *r_tot_y)
|
||||
void BLI_box_pack_2d(
|
||||
BoxPack *boxarray, const uint len, const bool sort_boxes, float *r_tot_x, float *r_tot_y)
|
||||
{
|
||||
uint box_index, verts_pack_len, i, j, k;
|
||||
uint *vertex_pack_indices; /* an array of indices used for sorting verts */
|
||||
|
@ -284,8 +285,11 @@ void BLI_box_pack_2d(BoxPack *boxarray, const uint len, float *r_tot_x, float *r
|
|||
return;
|
||||
}
|
||||
|
||||
/* Sort boxes, biggest first */
|
||||
qsort(boxarray, (size_t)len, sizeof(BoxPack), box_areasort);
|
||||
if (sort_boxes) {
|
||||
/* Sort boxes, biggest first.
|
||||
* Be careful, qsort is not deterministic! */
|
||||
qsort(boxarray, (size_t)len, sizeof(BoxPack), box_areasort);
|
||||
}
|
||||
|
||||
/* Add verts to the boxes, these are only used internally. */
|
||||
vert = MEM_mallocN(sizeof(BoxVert[4]) * (size_t)len, "BoxPack Verts");
|
||||
|
|
|
@ -142,7 +142,7 @@ static bool get_channel_bounds(bAnimContext *ac,
|
|||
|
||||
/* Pad the given rctf with regions that could block the view.
|
||||
* For example Markers and Time Scrubbing. */
|
||||
static void add_region_padding(bContext *C, bAnimContext *ac, rctf *bounds)
|
||||
static void add_region_padding(bContext *C, ARegion *region, rctf *bounds)
|
||||
{
|
||||
BLI_rctf_scale(bounds, 1.1f);
|
||||
|
||||
|
@ -150,9 +150,8 @@ static void add_region_padding(bContext *C, bAnimContext *ac, rctf *bounds)
|
|||
const float pad_bottom = BLI_listbase_is_empty(ED_context_get_markers(C)) ?
|
||||
V2D_SCROLL_HANDLE_HEIGHT :
|
||||
UI_MARKER_MARGIN_Y;
|
||||
BLI_rctf_pad_y(bounds, ac->region->winy, pad_bottom, pad_top);
|
||||
BLI_rctf_pad_y(bounds, region->winy, pad_bottom, pad_top);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
@ -731,6 +730,45 @@ void ANIM_flush_setting_anim_channels(bAnimContext *ac,
|
|||
anim_flush_channel_setting_down(ac, setting, mode, match, matchLevel);
|
||||
}
|
||||
|
||||
void ANIM_frame_channel_y_extents(bContext *C, bAnimContext *ac)
|
||||
{
|
||||
|
||||
ARegion *window_region = BKE_area_find_region_type(ac->area, RGN_TYPE_WINDOW);
|
||||
|
||||
if (!window_region) {
|
||||
return;
|
||||
}
|
||||
|
||||
ListBase anim_data = {NULL, NULL};
|
||||
const int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS |
|
||||
ANIMFILTER_FCURVESONLY);
|
||||
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
|
||||
|
||||
rctf bounds = {.xmin = FLT_MAX, .xmax = -FLT_MAX, .ymin = FLT_MAX, .ymax = -FLT_MAX};
|
||||
const bool include_handles = false;
|
||||
const float frame_range[2] = {window_region->v2d.cur.xmin, window_region->v2d.cur.xmax};
|
||||
|
||||
LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) {
|
||||
rctf channel_bounds;
|
||||
const bool found_bounds = get_channel_bounds(
|
||||
ac, ale, frame_range, include_handles, &channel_bounds);
|
||||
if (found_bounds) {
|
||||
BLI_rctf_union(&bounds, &channel_bounds);
|
||||
}
|
||||
}
|
||||
|
||||
if (!BLI_rctf_is_valid(&bounds)) {
|
||||
ANIM_animdata_freelist(&anim_data);
|
||||
return;
|
||||
}
|
||||
|
||||
add_region_padding(C, window_region, &bounds);
|
||||
|
||||
window_region->v2d.cur.ymin = bounds.ymin;
|
||||
window_region->v2d.cur.ymax = bounds.ymax;
|
||||
|
||||
ANIM_animdata_freelist(&anim_data);
|
||||
}
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
@ -3805,7 +3843,7 @@ static int graphkeys_view_selected_channels_exec(bContext *C, wmOperator *op)
|
|||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
add_region_padding(C, &ac, &bounds);
|
||||
add_region_padding(C, window_region, &bounds);
|
||||
|
||||
if (ac.spacetype == SPACE_ACTION) {
|
||||
bounds.ymin = window_region->v2d.cur.ymin;
|
||||
|
@ -3893,7 +3931,7 @@ static int graphkeys_channel_view_pick_invoke(bContext *C, wmOperator *op, const
|
|||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
add_region_padding(C, &ac, &bounds);
|
||||
add_region_padding(C, window_region, &bounds);
|
||||
|
||||
if (ac.spacetype == SPACE_ACTION) {
|
||||
bounds.ymin = window_region->v2d.cur.ymin;
|
||||
|
|
|
@ -676,6 +676,8 @@ void ANIM_flush_setting_anim_channels(bAnimContext *ac,
|
|||
eAnimChannel_Settings setting,
|
||||
eAnimChannels_SetFlag mode);
|
||||
|
||||
void ANIM_frame_channel_y_extents(struct bContext *C, bAnimContext *ac);
|
||||
|
||||
/**
|
||||
* Set selection state of all animation channels in the context.
|
||||
*/
|
||||
|
|
|
@ -52,7 +52,8 @@ class CurvesEffect {
|
|||
virtual ~CurvesEffect() = default;
|
||||
virtual void execute(CurvesGeometry &curves,
|
||||
Span<int> curve_indices,
|
||||
Span<float> move_distances_cu) = 0;
|
||||
Span<float> move_distances_cu,
|
||||
MutableSpan<float3> positions_cu) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -85,10 +86,10 @@ class ShrinkCurvesEffect : public CurvesEffect {
|
|||
|
||||
void execute(CurvesGeometry &curves,
|
||||
const Span<int> curve_indices,
|
||||
const Span<float> move_distances_cu) override
|
||||
const Span<float> move_distances_cu,
|
||||
MutableSpan<float3> positions_cu) override
|
||||
{
|
||||
const OffsetIndices points_by_curve = curves.points_by_curve();
|
||||
MutableSpan<float3> positions_cu = curves.positions_for_write();
|
||||
threading::parallel_for(curve_indices.index_range(), 256, [&](const IndexRange range) {
|
||||
ParameterizationBuffers data;
|
||||
for (const int influence_i : range) {
|
||||
|
@ -135,10 +136,10 @@ class ShrinkCurvesEffect : public CurvesEffect {
|
|||
class ExtrapolateCurvesEffect : public CurvesEffect {
|
||||
void execute(CurvesGeometry &curves,
|
||||
const Span<int> curve_indices,
|
||||
const Span<float> move_distances_cu) override
|
||||
const Span<float> move_distances_cu,
|
||||
MutableSpan<float3> positions_cu) override
|
||||
{
|
||||
const OffsetIndices points_by_curve = curves.points_by_curve();
|
||||
MutableSpan<float3> positions_cu = curves.positions_for_write();
|
||||
threading::parallel_for(curve_indices.index_range(), 256, [&](const IndexRange range) {
|
||||
MoveAndResampleBuffers resample_buffer;
|
||||
for (const int influence_i : range) {
|
||||
|
@ -175,10 +176,10 @@ class ScaleCurvesEffect : public CurvesEffect {
|
|||
|
||||
void execute(CurvesGeometry &curves,
|
||||
const Span<int> curve_indices,
|
||||
const Span<float> move_distances_cu) override
|
||||
const Span<float> move_distances_cu,
|
||||
MutableSpan<float3> positions_cu) override
|
||||
{
|
||||
const OffsetIndices points_by_curve = curves.points_by_curve();
|
||||
MutableSpan<float3> positions_cu = curves.positions_for_write();
|
||||
threading::parallel_for(curve_indices.index_range(), 256, [&](const IndexRange range) {
|
||||
for (const int influence_i : range) {
|
||||
const int curve_i = curve_indices[influence_i];
|
||||
|
@ -322,9 +323,11 @@ struct CurvesEffectOperationExecutor {
|
|||
}
|
||||
|
||||
/* Execute effect. */
|
||||
MutableSpan<float3> positions_cu = curves_->positions_for_write();
|
||||
threading::parallel_for_each(influences_for_thread, [&](const Influences &influences) {
|
||||
BLI_assert(influences.curve_indices.size() == influences.move_distances_cu.size());
|
||||
self_->effect_->execute(*curves_, influences.curve_indices, influences.move_distances_cu);
|
||||
self_->effect_->execute(
|
||||
*curves_, influences.curve_indices, influences.move_distances_cu, positions_cu);
|
||||
});
|
||||
|
||||
curves_->tag_positions_changed();
|
||||
|
|
|
@ -88,6 +88,7 @@ class PackIsland {
|
|||
void finalize_geometry(const UVPackIsland_Params ¶ms, MemArena *arena, Heap *heap);
|
||||
|
||||
private:
|
||||
void calculate_pivot(); /* Choose a pivot based on triangles. */
|
||||
blender::Vector<float2> triangle_vertices_;
|
||||
friend class Occupancy;
|
||||
};
|
||||
|
|
|
@ -131,7 +131,8 @@ void PackIsland::finalize_geometry(const UVPackIsland_Params ¶ms, MemArena *
|
|||
if (shape_method == ED_UVPACK_SHAPE_CONVEX) {
|
||||
/* Compute convex hull of existing triangles. */
|
||||
if (triangle_vertices_.size() <= 3) {
|
||||
return; /* Trivial case, nothing to do. */
|
||||
calculate_pivot();
|
||||
return; /* Trivial case, calculate pivot only. */
|
||||
}
|
||||
|
||||
int vert_count = int(triangle_vertices_.size());
|
||||
|
@ -156,7 +157,11 @@ void PackIsland::finalize_geometry(const UVPackIsland_Params ¶ms, MemArena *
|
|||
|
||||
BLI_heap_clear(heap, nullptr);
|
||||
}
|
||||
calculate_pivot();
|
||||
}
|
||||
|
||||
void PackIsland::calculate_pivot()
|
||||
{
|
||||
Bounds<float2> triangle_bounds = *bounds::min_max(triangle_vertices_.as_span());
|
||||
float2 aabb_min = triangle_bounds.min;
|
||||
float2 aabb_max = triangle_bounds.max;
|
||||
|
@ -821,7 +826,7 @@ static float pack_islands_scale_margin(const Span<PackIsland *> islands,
|
|||
&max_v);
|
||||
break;
|
||||
default:
|
||||
BLI_box_pack_2d(box_array, int(max_box_pack), &max_u, &max_v);
|
||||
BLI_box_pack_2d(box_array, int(max_box_pack), false, &max_u, &max_v);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -1013,15 +1013,14 @@ static PChart **p_split_charts(ParamHandle *handle, PChart *chart, int ncharts)
|
|||
static PFace *p_face_add(ParamHandle *handle)
|
||||
{
|
||||
PFace *f;
|
||||
PEdge *e1, *e2, *e3;
|
||||
|
||||
/* allocate */
|
||||
f = (PFace *)BLI_memarena_alloc(handle->arena, sizeof(*f));
|
||||
f->flag = 0; /* init ! */
|
||||
|
||||
e1 = (PEdge *)BLI_memarena_alloc(handle->arena, sizeof(*e1));
|
||||
e2 = (PEdge *)BLI_memarena_alloc(handle->arena, sizeof(*e2));
|
||||
e3 = (PEdge *)BLI_memarena_alloc(handle->arena, sizeof(*e3));
|
||||
PEdge *e1 = (PEdge *)BLI_memarena_calloc(handle->arena, sizeof(*e1));
|
||||
PEdge *e2 = (PEdge *)BLI_memarena_calloc(handle->arena, sizeof(*e2));
|
||||
PEdge *e3 = (PEdge *)BLI_memarena_calloc(handle->arena, sizeof(*e3));
|
||||
|
||||
/* set up edges */
|
||||
f->edge = e1;
|
||||
|
@ -1031,14 +1030,6 @@ static PFace *p_face_add(ParamHandle *handle)
|
|||
e2->next = e3;
|
||||
e3->next = e1;
|
||||
|
||||
e1->pair = nullptr;
|
||||
e2->pair = nullptr;
|
||||
e3->pair = nullptr;
|
||||
|
||||
e1->flag = 0;
|
||||
e2->flag = 0;
|
||||
e3->flag = 0;
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,9 @@
|
|||
#include "DNA_collection_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BLI_memory_utils.hh"
|
||||
#include "IO_ply.h"
|
||||
|
||||
#include "ply_data.hh"
|
||||
#include "ply_export.hh"
|
||||
|
|
|
@ -6,20 +6,12 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "IO_ply.h"
|
||||
#include "ply_data.hh"
|
||||
#include "ply_file_buffer.hh"
|
||||
struct bContext;
|
||||
struct PLYExportParams;
|
||||
|
||||
namespace blender::io::ply {
|
||||
|
||||
/* Main export function used from within Blender. */
|
||||
void exporter_main(bContext *C, const PLYExportParams &export_params);
|
||||
|
||||
/* Used from tests, where full bContext does not exist. */
|
||||
void exporter_main(Main *bmain,
|
||||
Scene *scene,
|
||||
ViewLayer *view_layer,
|
||||
bContext *C,
|
||||
const PLYExportParams &export_params);
|
||||
|
||||
} // namespace blender::io::ply
|
||||
|
|
|
@ -6,11 +6,11 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "ply_data.hh"
|
||||
#include "ply_file_buffer.hh"
|
||||
|
||||
namespace blender::io::ply {
|
||||
|
||||
class FileBuffer;
|
||||
struct PlyData;
|
||||
|
||||
void write_vertices(FileBuffer &buffer, const PlyData &ply_data);
|
||||
|
||||
void write_faces(FileBuffer &buffer, const PlyData &ply_data);
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
*/
|
||||
|
||||
#include "BKE_blender_version.h"
|
||||
#include "BKE_customdata.h"
|
||||
|
||||
#include "IO_ply.h"
|
||||
#include "ply_data.hh"
|
||||
|
|
|
@ -6,11 +6,13 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "ply_data.hh"
|
||||
#include "ply_file_buffer.hh"
|
||||
struct PLYExportParams;
|
||||
|
||||
namespace blender::io::ply {
|
||||
|
||||
class FileBuffer;
|
||||
struct PlyData;
|
||||
|
||||
void write_header(FileBuffer &buffer,
|
||||
const PlyData &ply_data,
|
||||
const PLYExportParams &export_params);
|
||||
|
|
|
@ -4,38 +4,27 @@
|
|||
* \ingroup ply
|
||||
*/
|
||||
|
||||
#include "BLI_array.hh"
|
||||
#include "BLI_math.h"
|
||||
#include "ply_export_load_plydata.hh"
|
||||
#include "IO_ply.h"
|
||||
#include "ply_data.hh"
|
||||
|
||||
#include "BKE_attribute.hh"
|
||||
#include "BKE_lib_id.h"
|
||||
#include "BKE_mesh.hh"
|
||||
#include "BKE_mesh_mapping.h"
|
||||
#include "BKE_object.h"
|
||||
|
||||
#include "DEG_depsgraph.h"
|
||||
#include "DEG_depsgraph_build.h"
|
||||
#include "BLI_hash.hh"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_vector.hh"
|
||||
#include "DEG_depsgraph_query.h"
|
||||
|
||||
#include "DNA_layer_types.h"
|
||||
|
||||
#include "IO_ply.h"
|
||||
|
||||
#include "bmesh.h"
|
||||
#include "bmesh_tools.h"
|
||||
|
||||
#include <tools/bmesh_triangulate.h>
|
||||
|
||||
#include "ply_data.hh"
|
||||
#include "ply_export_load_plydata.hh"
|
||||
|
||||
namespace blender::io::ply {
|
||||
|
||||
float world_and_axes_transform_[4][4];
|
||||
float world_and_axes_normal_transform_[3][3];
|
||||
bool mirrored_transform_;
|
||||
|
||||
Mesh *do_triangulation(const Mesh *mesh, bool force_triangulation)
|
||||
static Mesh *do_triangulation(const Mesh *mesh, bool force_triangulation)
|
||||
{
|
||||
const BMeshCreateParams bm_create_params = {false};
|
||||
BMeshFromMeshParams bm_convert_params{};
|
||||
|
@ -50,28 +39,110 @@ Mesh *do_triangulation(const Mesh *mesh, bool force_triangulation)
|
|||
return temp_mesh;
|
||||
}
|
||||
|
||||
void set_world_axes_transform(Object *object, const eIOAxis forward, const eIOAxis up)
|
||||
static void set_world_axes_transform(Object *object,
|
||||
const eIOAxis forward,
|
||||
const eIOAxis up,
|
||||
float r_world_and_axes_transform[4][4],
|
||||
float r_world_and_axes_normal_transform[3][3])
|
||||
{
|
||||
float axes_transform[3][3];
|
||||
unit_m3(axes_transform);
|
||||
/* +Y-forward and +Z-up are the default Blender axis settings. */
|
||||
mat3_from_axis_conversion(forward, up, IO_AXIS_Y, IO_AXIS_Z, axes_transform);
|
||||
mul_m4_m3m4(world_and_axes_transform_, axes_transform, object->object_to_world);
|
||||
mul_m4_m3m4(r_world_and_axes_transform, axes_transform, object->object_to_world);
|
||||
/* mul_m4_m3m4 does not transform last row of obmat, i.e. location data. */
|
||||
mul_v3_m3v3(world_and_axes_transform_[3], axes_transform, object->object_to_world[3]);
|
||||
world_and_axes_transform_[3][3] = object->object_to_world[3][3];
|
||||
mul_v3_m3v3(r_world_and_axes_transform[3], axes_transform, object->object_to_world[3]);
|
||||
r_world_and_axes_transform[3][3] = object->object_to_world[3][3];
|
||||
|
||||
/* Normals need inverse transpose of the regular matrix to handle non-uniform scale. */
|
||||
float normal_matrix[3][3];
|
||||
copy_m3_m4(normal_matrix, world_and_axes_transform_);
|
||||
invert_m3_m3(world_and_axes_normal_transform_, normal_matrix);
|
||||
transpose_m3(world_and_axes_normal_transform_);
|
||||
mirrored_transform_ = is_negative_m3(world_and_axes_normal_transform_);
|
||||
copy_m3_m4(normal_matrix, r_world_and_axes_transform);
|
||||
invert_m3_m3(r_world_and_axes_normal_transform, normal_matrix);
|
||||
transpose_m3(r_world_and_axes_normal_transform);
|
||||
}
|
||||
|
||||
struct uv_vertex_key {
|
||||
float2 uv;
|
||||
int vertex_index;
|
||||
|
||||
bool operator==(const uv_vertex_key &r) const
|
||||
{
|
||||
return (uv == r.uv && vertex_index == r.vertex_index);
|
||||
}
|
||||
|
||||
uint64_t hash() const
|
||||
{
|
||||
return get_default_hash_3(uv.x, uv.y, vertex_index);
|
||||
}
|
||||
};
|
||||
|
||||
static void generate_vertex_map(const Mesh *mesh,
|
||||
const PLYExportParams &export_params,
|
||||
Vector<int> &r_ply_to_vertex,
|
||||
Vector<int> &r_vertex_to_ply,
|
||||
Vector<int> &r_loop_to_ply,
|
||||
Vector<float2> &r_uvs)
|
||||
{
|
||||
bool export_uv = false;
|
||||
VArraySpan<float2> uv_map;
|
||||
if (export_params.export_uv) {
|
||||
const StringRef uv_name = CustomData_get_active_layer_name(&mesh->ldata, CD_PROP_FLOAT2);
|
||||
if (!uv_name.is_empty()) {
|
||||
const bke::AttributeAccessor attributes = mesh->attributes();
|
||||
uv_map = attributes.lookup<float2>(uv_name, ATTR_DOMAIN_CORNER);
|
||||
export_uv = !uv_map.is_empty();
|
||||
}
|
||||
}
|
||||
|
||||
const Span<int> corner_verts = mesh->corner_verts();
|
||||
r_vertex_to_ply.resize(mesh->totvert, -1);
|
||||
r_loop_to_ply.resize(mesh->totloop, -1);
|
||||
|
||||
/* If we do not export or have UVs, then mapping of vertex indices is simple. */
|
||||
if (!export_uv) {
|
||||
r_ply_to_vertex.resize(mesh->totvert);
|
||||
for (int index = 0; index < mesh->totvert; index++) {
|
||||
r_vertex_to_ply[index] = index;
|
||||
r_ply_to_vertex[index] = index;
|
||||
}
|
||||
for (int index = 0; index < mesh->totloop; index++) {
|
||||
r_loop_to_ply[index] = corner_verts[index];
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* We are exporting UVs. Need to build mappings of what
|
||||
* any unique (vertex, UV) values will map into the PLY data. */
|
||||
Map<uv_vertex_key, int> vertex_map;
|
||||
vertex_map.reserve(mesh->totvert);
|
||||
r_ply_to_vertex.reserve(mesh->totvert);
|
||||
r_uvs.reserve(mesh->totvert);
|
||||
|
||||
for (int loop_index = 0; loop_index < int(corner_verts.size()); loop_index++) {
|
||||
int vertex_index = corner_verts[loop_index];
|
||||
uv_vertex_key key{uv_map[loop_index], vertex_index};
|
||||
int ply_index = vertex_map.lookup_or_add(key, int(vertex_map.size()));
|
||||
r_vertex_to_ply[vertex_index] = ply_index;
|
||||
r_loop_to_ply[loop_index] = ply_index;
|
||||
while (r_uvs.size() <= ply_index) {
|
||||
r_uvs.append(key.uv);
|
||||
r_ply_to_vertex.append(key.vertex_index);
|
||||
}
|
||||
}
|
||||
|
||||
/* Add zero UVs for any loose vertices. */
|
||||
for (int vertex_index = 0; vertex_index < mesh->totvert; vertex_index++) {
|
||||
if (r_vertex_to_ply[vertex_index] != -1)
|
||||
continue;
|
||||
int ply_index = int(r_uvs.size());
|
||||
r_vertex_to_ply[vertex_index] = ply_index;
|
||||
r_uvs.append({0, 0});
|
||||
r_ply_to_vertex.append(vertex_index);
|
||||
}
|
||||
}
|
||||
|
||||
void load_plydata(PlyData &plyData, Depsgraph *depsgraph, const PLYExportParams &export_params)
|
||||
{
|
||||
|
||||
DEGObjectIterSettings deg_iter_settings{};
|
||||
deg_iter_settings.depsgraph = depsgraph;
|
||||
deg_iter_settings.flags = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY |
|
||||
|
@ -111,73 +182,56 @@ void load_plydata(PlyData &plyData, Depsgraph *depsgraph, const PLYExportParams
|
|||
manually_free_mesh = true;
|
||||
}
|
||||
|
||||
const float2 *uv_map = static_cast<const float2 *>(
|
||||
CustomData_get_layer(&mesh->ldata, CD_PROP_FLOAT2));
|
||||
Vector<int> ply_to_vertex, vertex_to_ply, loop_to_ply;
|
||||
Vector<float2> uvs;
|
||||
generate_vertex_map(mesh, export_params, ply_to_vertex, vertex_to_ply, loop_to_ply, uvs);
|
||||
|
||||
Map<UV_vertex_key, int> vertex_map;
|
||||
generate_vertex_map(mesh, uv_map, export_params, vertex_map);
|
||||
float world_and_axes_transform[4][4];
|
||||
float world_and_axes_normal_transform[3][3];
|
||||
set_world_axes_transform(&export_object_eval_,
|
||||
export_params.forward_axis,
|
||||
export_params.up_axis,
|
||||
world_and_axes_transform,
|
||||
world_and_axes_normal_transform);
|
||||
|
||||
set_world_axes_transform(
|
||||
&export_object_eval_, export_params.forward_axis, export_params.up_axis);
|
||||
|
||||
/* Load faces into plyData. */
|
||||
/* Face data. */
|
||||
plyData.face_vertices.reserve(mesh->totloop);
|
||||
plyData.face_sizes.reserve(mesh->totpoly);
|
||||
int loop_offset = 0;
|
||||
const Span<int> corner_verts = mesh->corner_verts();
|
||||
for (const MPoly &poly : mesh->polys()) {
|
||||
const Span<int> mesh_poly_verts = corner_verts.slice(poly.loopstart, poly.totloop);
|
||||
Array<uint32_t> poly_verts(mesh_poly_verts.size());
|
||||
|
||||
for (int i = 0; i < mesh_poly_verts.size(); ++i) {
|
||||
float2 uv;
|
||||
if (export_params.export_uv && uv_map != nullptr) {
|
||||
uv = uv_map[i + loop_offset];
|
||||
}
|
||||
else {
|
||||
uv = {0, 0};
|
||||
}
|
||||
UV_vertex_key key = UV_vertex_key(uv, mesh_poly_verts[i]);
|
||||
int ply_vertex_index = vertex_map.lookup(key);
|
||||
plyData.face_vertices.append(ply_vertex_index + vertex_offset);
|
||||
for (int i = 0; i < poly.totloop; ++i) {
|
||||
int ply_index = loop_to_ply[i + loop_offset];
|
||||
BLI_assert(ply_index >= 0 && ply_index < ply_to_vertex.size());
|
||||
plyData.face_vertices.append(ply_index + vertex_offset);
|
||||
}
|
||||
loop_offset += poly.totloop;
|
||||
plyData.face_sizes.append(poly.totloop);
|
||||
}
|
||||
|
||||
Array<int> mesh_vertex_index_LUT(vertex_map.size());
|
||||
Array<int> ply_vertex_index_LUT(mesh->totvert);
|
||||
Array<float2> uv_coordinates(vertex_map.size());
|
||||
|
||||
for (auto const &[key, ply_vertex_index] : vertex_map.items()) {
|
||||
mesh_vertex_index_LUT[ply_vertex_index] = key.mesh_vertex_index;
|
||||
ply_vertex_index_LUT[key.mesh_vertex_index] = ply_vertex_index;
|
||||
uv_coordinates[ply_vertex_index] = key.UV;
|
||||
}
|
||||
|
||||
/* Vertices */
|
||||
for (int i = 0; i < vertex_map.size(); ++i) {
|
||||
float3 r_coords;
|
||||
copy_v3_v3(r_coords, mesh->vert_positions()[mesh_vertex_index_LUT[i]]);
|
||||
mul_m4_v3(world_and_axes_transform_, r_coords);
|
||||
mul_v3_fl(r_coords, export_params.global_scale);
|
||||
plyData.vertices.append(r_coords);
|
||||
plyData.vertices.reserve(ply_to_vertex.size());
|
||||
Span<float3> vert_positions = mesh->vert_positions();
|
||||
for (int vertex_index : ply_to_vertex) {
|
||||
float3 pos = vert_positions[vertex_index];
|
||||
mul_m4_v3(world_and_axes_transform, pos);
|
||||
mul_v3_fl(pos, export_params.global_scale);
|
||||
plyData.vertices.append(pos);
|
||||
}
|
||||
|
||||
/* UV's */
|
||||
if (export_params.export_uv) {
|
||||
for (int i = 0; i < vertex_map.size(); ++i) {
|
||||
plyData.uv_coordinates.append(uv_coordinates[i]);
|
||||
}
|
||||
if (!uvs.is_empty()) {
|
||||
BLI_assert(uvs.size() == ply_to_vertex.size());
|
||||
plyData.uv_coordinates = uvs;
|
||||
}
|
||||
|
||||
/* Normals */
|
||||
if (export_params.export_normals) {
|
||||
plyData.vertex_normals.reserve(ply_to_vertex.size());
|
||||
const Span<float3> vert_normals = mesh->vert_normals();
|
||||
for (int i = 0; i < vertex_map.size(); i++) {
|
||||
mul_m3_v3(world_and_axes_normal_transform_,
|
||||
float3(vert_normals[mesh_vertex_index_LUT[i]]));
|
||||
plyData.vertex_normals.append(vert_normals[mesh_vertex_index_LUT[i]]);
|
||||
for (int vertex_index : ply_to_vertex) {
|
||||
float3 normal = vert_normals[vertex_index];
|
||||
mul_m3_v3(world_and_axes_normal_transform, normal);
|
||||
plyData.vertex_normals.append(normal);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -189,27 +243,28 @@ void load_plydata(PlyData &plyData, Depsgraph *depsgraph, const PLYExportParams
|
|||
const VArray<ColorGeometry4f> color_attribute =
|
||||
attributes.lookup_or_default<ColorGeometry4f>(
|
||||
name, ATTR_DOMAIN_POINT, {0.0f, 0.0f, 0.0f, 0.0f});
|
||||
|
||||
for (int i = 0; i < vertex_map.size(); i++) {
|
||||
ColorGeometry4f colorGeometry = color_attribute[mesh_vertex_index_LUT[i]];
|
||||
float4 vertColor(colorGeometry.r, colorGeometry.g, colorGeometry.b, colorGeometry.a);
|
||||
if (export_params.vertex_colors == PLY_VERTEX_COLOR_SRGB) {
|
||||
linearrgb_to_srgb_v4(vertColor, vertColor);
|
||||
if (!color_attribute.is_empty()) {
|
||||
plyData.vertex_colors.reserve(ply_to_vertex.size());
|
||||
for (int vertex_index : ply_to_vertex) {
|
||||
float4 color = float4(color_attribute[vertex_index]);
|
||||
if (export_params.vertex_colors == PLY_VERTEX_COLOR_SRGB) {
|
||||
linearrgb_to_srgb_v4(color, color);
|
||||
}
|
||||
plyData.vertex_colors.append(color);
|
||||
}
|
||||
plyData.vertex_colors.append(vertColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Edges */
|
||||
/* Loose edges */
|
||||
const bke::LooseEdgeCache &loose_edges = mesh->loose_edges();
|
||||
if (loose_edges.count > 0) {
|
||||
Span<MEdge> edges = mesh->edges();
|
||||
for (int i = 0; i < edges.size(); ++i) {
|
||||
if (loose_edges.is_loose_bits[i]) {
|
||||
int index_one = ply_vertex_index_LUT[edges[i].v1];
|
||||
int index_two = ply_vertex_index_LUT[edges[i].v2];
|
||||
plyData.edges.append({index_one, index_two});
|
||||
int v1 = vertex_to_ply[edges[i].v1];
|
||||
int v2 = vertex_to_ply[edges[i].v2];
|
||||
plyData.edges.append({v1, v2});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -223,55 +278,4 @@ void load_plydata(PlyData &plyData, Depsgraph *depsgraph, const PLYExportParams
|
|||
DEG_OBJECT_ITER_END;
|
||||
}
|
||||
|
||||
void generate_vertex_map(const Mesh *mesh,
|
||||
const float2 *uv_map,
|
||||
const PLYExportParams &export_params,
|
||||
Map<UV_vertex_key, int> &r_map)
|
||||
{
|
||||
|
||||
const Span<MPoly> polys = mesh->polys();
|
||||
const Span<int> corner_verts = mesh->corner_verts();
|
||||
const int totvert = mesh->totvert;
|
||||
|
||||
r_map.reserve(totvert);
|
||||
|
||||
if (uv_map == nullptr || !export_params.export_uv) {
|
||||
for (int vertex_index = 0; vertex_index < totvert; ++vertex_index) {
|
||||
UV_vertex_key key = UV_vertex_key({0, 0}, vertex_index);
|
||||
r_map.add_new(key, int(r_map.size()));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const float limit[2] = {STD_UV_CONNECT_LIMIT, STD_UV_CONNECT_LIMIT};
|
||||
UvVertMap *uv_vert_map = BKE_mesh_uv_vert_map_create(polys.data(),
|
||||
nullptr,
|
||||
nullptr,
|
||||
corner_verts.data(),
|
||||
reinterpret_cast<const float(*)[2]>(uv_map),
|
||||
uint(polys.size()),
|
||||
totvert,
|
||||
limit,
|
||||
false,
|
||||
false);
|
||||
|
||||
for (int vertex_index = 0; vertex_index < totvert; vertex_index++) {
|
||||
const UvMapVert *uv_vert = BKE_mesh_uv_vert_map_get_vert(uv_vert_map, vertex_index);
|
||||
|
||||
if (uv_vert == nullptr) {
|
||||
UV_vertex_key key = UV_vertex_key({0, 0}, vertex_index);
|
||||
r_map.add_new(key, int(r_map.size()));
|
||||
}
|
||||
|
||||
for (; uv_vert; uv_vert = uv_vert->next) {
|
||||
/* Store UV vertex coordinates. */
|
||||
const int loopstart = polys[uv_vert->poly_index].loopstart;
|
||||
float2 vert_uv_coords(uv_map[loopstart + uv_vert->loop_of_poly_index]);
|
||||
UV_vertex_key key = UV_vertex_key(vert_uv_coords, vertex_index);
|
||||
r_map.add(key, int(r_map.size()));
|
||||
}
|
||||
}
|
||||
BKE_mesh_uv_vert_map_free(uv_vert_map);
|
||||
}
|
||||
|
||||
} // namespace blender::io::ply
|
||||
|
|
|
@ -6,52 +6,13 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "BKE_mesh.h"
|
||||
#include "BLI_math.h"
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_mesh_mapping.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BLI_hash.hh"
|
||||
#include "BLI_math.h"
|
||||
|
||||
#include "RNA_types.h"
|
||||
|
||||
#include "DEG_depsgraph.h"
|
||||
#include "DEG_depsgraph_build.h"
|
||||
#include "DEG_depsgraph_query.h"
|
||||
|
||||
#include "DNA_layer_types.h"
|
||||
|
||||
#include "ply_data.hh"
|
||||
struct Depsgraph;
|
||||
struct PLYExportParams;
|
||||
|
||||
namespace blender::io::ply {
|
||||
|
||||
Mesh *do_triangulation(const Mesh *mesh, bool force_triangulation);
|
||||
void set_world_axes_transform(Object *object, const eIOAxis forward, const eIOAxis up);
|
||||
|
||||
struct UV_vertex_key {
|
||||
float2 UV;
|
||||
int mesh_vertex_index;
|
||||
|
||||
UV_vertex_key(float2 UV, int vertex_index) : UV(UV), mesh_vertex_index(vertex_index) {}
|
||||
|
||||
bool operator==(const UV_vertex_key &r) const
|
||||
{
|
||||
return (UV == r.UV && mesh_vertex_index == r.mesh_vertex_index);
|
||||
}
|
||||
|
||||
uint64_t hash() const
|
||||
{
|
||||
return get_default_hash_3(UV.x, UV.y, mesh_vertex_index);
|
||||
}
|
||||
};
|
||||
|
||||
void generate_vertex_map(const Mesh *mesh,
|
||||
const float2 *uv_map,
|
||||
const PLYExportParams &export_params,
|
||||
Map<UV_vertex_key, int> &r_map);
|
||||
struct PlyData;
|
||||
|
||||
void load_plydata(PlyData &plyData, Depsgraph *depsgraph, const PLYExportParams &export_params);
|
||||
|
||||
} // namespace blender::io::ply
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
#include "ply_file_buffer_binary.hh"
|
||||
|
||||
#include "BLI_math_vector_types.hh"
|
||||
|
||||
namespace blender::io::ply {
|
||||
void FileBufferBinary::write_vertex(float x, float y, float z)
|
||||
{
|
||||
|
|
|
@ -6,20 +6,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
#include "BLI_array.hh"
|
||||
#include "BLI_compiler_attrs.h"
|
||||
#include "BLI_fileops.h"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
#include "BLI_string_ref.hh"
|
||||
#include "BLI_utility_mixins.hh"
|
||||
|
||||
#include "ply_file_buffer.hh"
|
||||
|
||||
#include <bitset>
|
||||
|
||||
namespace blender::io::ply {
|
||||
class FileBufferBinary : public FileBuffer {
|
||||
using FileBuffer::FileBuffer;
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "BLI_array.hh"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
#include "BLI_vector.hh"
|
||||
|
||||
|
|
|
@ -484,30 +484,30 @@ TEST_F(ply_exporter_ply_data_test, CubeLooseEdgesLoadPLYDataUV)
|
|||
PlyData plyData = load_ply_data_from_blendfile(
|
||||
"io_tests/blend_geometry/cube_loose_edges_verts.blend", params);
|
||||
float3 exp_vertices[] = {
|
||||
{1, 1, 1},
|
||||
{-1, 1, -1},
|
||||
{1, 1, -1},
|
||||
{1, -1, 1},
|
||||
{1, -1, -1},
|
||||
{-1, 1, 1},
|
||||
{-1, 1, -1},
|
||||
{-1, 1, -1},
|
||||
{-1, -1, 1},
|
||||
{-1, -1, -1},
|
||||
{-1, 1, -1},
|
||||
{-1, 1, 1},
|
||||
{1, 1, 1},
|
||||
{1, -1, 1},
|
||||
{-1, -1, 1},
|
||||
};
|
||||
float2 exp_uv[] = {
|
||||
{0.625f, 0.5f},
|
||||
{0.375f, 0.5f},
|
||||
{0, 0},
|
||||
{0.375f, 0.75f},
|
||||
{0.625f, 0.25f},
|
||||
{0.125f, 0.5f},
|
||||
{0.375f, 0.25f},
|
||||
{0, 0},
|
||||
{0.375f, 0.5f},
|
||||
{0.375f, 0.75f},
|
||||
{0.125f, 0.75f},
|
||||
{0.375f, 0.25f},
|
||||
{0.625f, 0.25f},
|
||||
{0.625f, 0.5f},
|
||||
{0, 0},
|
||||
{0, 0},
|
||||
};
|
||||
std::pair<int, int> exp_edges[] = {{8, 7}, {7, 4}};
|
||||
std::pair<int, int> exp_edges[] = {{3, 8}, {8, 5}};
|
||||
uint32_t exp_face_sizes[] = {4, 4};
|
||||
uint32_t exp_faces[] = {5, 1, 3, 8, 6, 4, 0, 1};
|
||||
uint32_t exp_faces[] = {0, 1, 2, 3, 4, 5, 6, 1};
|
||||
EXPECT_EQ(plyData.vertices.size(), 9);
|
||||
EXPECT_EQ(plyData.uv_coordinates.size(), 9);
|
||||
EXPECT_EQ(plyData.edges.size(), ARRAY_SIZE(exp_edges));
|
||||
|
|
|
@ -2376,6 +2376,18 @@ static void rna_SpaceGraphEditor_display_mode_update(bContext *C, PointerRNA *pt
|
|||
ED_area_tag_refresh(area);
|
||||
}
|
||||
|
||||
static void rna_SpaceGraphEditor_normalize_update(bContext *C, PointerRNA *UNUSED(ptr))
|
||||
{
|
||||
bAnimContext ac;
|
||||
|
||||
if (ANIM_animdata_get_context(C, &ac) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
ANIM_frame_channel_y_extents(C, &ac);
|
||||
ED_area_tag_refresh(ac.area);
|
||||
}
|
||||
|
||||
static bool rna_SpaceGraphEditor_has_ghost_curves_get(PointerRNA *ptr)
|
||||
{
|
||||
SpaceGraph *sipo = (SpaceGraph *)(ptr->data);
|
||||
|
@ -6414,7 +6426,9 @@ static void rna_def_space_graph(BlenderRNA *brna)
|
|||
"Use Normalization",
|
||||
"Display curves in normalized range from -1 to 1, "
|
||||
"for easier editing of multiple curves with different ranges");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL);
|
||||
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
|
||||
RNA_def_property_update(
|
||||
prop, NC_SPACE | ND_SPACE_GRAPH, "rna_SpaceGraphEditor_normalize_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_auto_normalization", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SIPO_NORMALIZE_FREEZE);
|
||||
|
|
|
@ -1404,8 +1404,9 @@ static PyObject *M_Geometry_box_pack_2d(PyObject *UNUSED(self), PyObject *boxlis
|
|||
return NULL; /* exception set */
|
||||
}
|
||||
|
||||
const bool sort_boxes = true; /* Caution: BLI_box_pack_2d sorting is non-deterministic. */
|
||||
/* Non Python function */
|
||||
BLI_box_pack_2d(boxarray, len, &tot_width, &tot_height);
|
||||
BLI_box_pack_2d(boxarray, len, sort_boxes, &tot_width, &tot_height);
|
||||
|
||||
boxPack_ToPyObject(boxlist, boxarray);
|
||||
MEM_freeN(boxarray);
|
||||
|
|
Loading…
Reference in New Issue