diff options
Diffstat (limited to 'intern')
61 files changed, 4233 insertions, 2556 deletions
diff --git a/intern/CMakeLists.txt b/intern/CMakeLists.txt index 4e780dc9f0f..fa18f4d793a 100644 --- a/intern/CMakeLists.txt +++ b/intern/CMakeLists.txt @@ -20,7 +20,6 @@ # add_subdirectory(atomic) # header only add_subdirectory(clog) -add_subdirectory(string) add_subdirectory(ghost) add_subdirectory(guardedalloc) add_subdirectory(libmv) diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 7cf615620a3..08641c05941 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -500,8 +500,9 @@ class CYCLES_RENDER_PT_light_paths_caustics(CyclesButtonsPanel, Panel): col = layout.column() col.prop(cscene, "blur_glossy") - col.prop(cscene, "caustics_reflective") - col.prop(cscene, "caustics_refractive") + col = layout.column(heading="Caustics", align=True) + col.prop(cscene, "caustics_reflective", text="Reflective") + col.prop(cscene, "caustics_refractive", text="Refractive") class CYCLES_RENDER_PT_motion_blur(CyclesButtonsPanel, Panel): @@ -762,22 +763,16 @@ class CYCLES_RENDER_PT_filter(CyclesButtonsPanel, Panel): rd = scene.render view_layer = context.view_layer - flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False) - - col = flow.column() + col = layout.column(heading="Include") col.prop(view_layer, "use_sky", text="Environment") - col = flow.column() col.prop(view_layer, "use_ao", text="Ambient Occlusion") - col = flow.column() col.prop(view_layer, "use_solid", text="Surfaces") - col = flow.column() col.prop(view_layer, "use_strand", text="Hair") - col = flow.column() col.prop(view_layer, "use_volumes", text="Volumes") if with_freestyle: - col = flow.column() - col.prop(view_layer, "use_freestyle", text="Freestyle") - col.active = rd.use_freestyle + sub = col.row(align=True) + sub.prop(view_layer, "use_freestyle", text="Freestyle") + sub.active = rd.use_freestyle class CYCLES_RENDER_PT_override(CyclesButtonsPanel, Panel): @@ -819,36 +814,27 @@ class CYCLES_RENDER_PT_passes_data(CyclesButtonsPanel, Panel): view_layer = context.view_layer cycles_view_layer = view_layer.cycles - flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False) - col = flow.column() + col = layout.column(heading="Include", align=True) col.prop(view_layer, "use_pass_combined") - col = flow.column() col.prop(view_layer, "use_pass_z") - col = flow.column() col.prop(view_layer, "use_pass_mist") - col = flow.column() col.prop(view_layer, "use_pass_normal") - col = flow.column() - col.prop(view_layer, "use_pass_vector") - col.active = not rd.use_motion_blur - col = flow.column() + sub = col.column() + sub.active = not rd.use_motion_blur + sub.prop(view_layer, "use_pass_vector") col.prop(view_layer, "use_pass_uv") - col = flow.column() + + col.prop(cycles_view_layer, "denoising_store_passes", text="Denoising Data") + + col = layout.column(heading="Indexes", align=True) col.prop(view_layer, "use_pass_object_index") - col = flow.column() col.prop(view_layer, "use_pass_material_index") - layout.separator() - - flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False) - col = flow.column() - col.prop(cycles_view_layer, "denoising_store_passes", text="Denoising Data") - col = flow.column() + col = layout.column(heading="Debug", align=True) col.prop(cycles_view_layer, "pass_debug_render_time", text="Render Time") - col = flow.column() col.prop(cycles_view_layer, "pass_debug_sample_count", text="Sample Count") - layout.separator() + layout.prop(view_layer, "pass_alpha_threshold") @@ -866,38 +852,26 @@ class CYCLES_RENDER_PT_passes_light(CyclesButtonsPanel, Panel): view_layer = context.view_layer cycles_view_layer = view_layer.cycles - split = layout.split(factor=0.35) - split.use_property_split = False - split.label(text="Diffuse") - row = split.row(align=True) - row.prop(view_layer, "use_pass_diffuse_direct", text="Direct", toggle=True) - row.prop(view_layer, "use_pass_diffuse_indirect", text="Indirect", toggle=True) - row.prop(view_layer, "use_pass_diffuse_color", text="Color", toggle=True) - - split = layout.split(factor=0.35) - split.use_property_split = False - split.label(text="Glossy") - row = split.row(align=True) - row.prop(view_layer, "use_pass_glossy_direct", text="Direct", toggle=True) - row.prop(view_layer, "use_pass_glossy_indirect", text="Indirect", toggle=True) - row.prop(view_layer, "use_pass_glossy_color", text="Color", toggle=True) - - split = layout.split(factor=0.35) - split.use_property_split = False - split.label(text="Transmission") - row = split.row(align=True) - row.prop(view_layer, "use_pass_transmission_direct", text="Direct", toggle=True) - row.prop(view_layer, "use_pass_transmission_indirect", text="Indirect", toggle=True) - row.prop(view_layer, "use_pass_transmission_color", text="Color", toggle=True) - - split = layout.split(factor=0.35) - split.use_property_split = False - split.label(text="Volume") - row = split.row(align=True) - row.prop(cycles_view_layer, "use_pass_volume_direct", text="Direct", toggle=True) - row.prop(cycles_view_layer, "use_pass_volume_indirect", text="Indirect", toggle=True) + col = layout.column(heading="Diffuse", align=True) + col.prop(view_layer, "use_pass_diffuse_direct", text="Direct") + col.prop(view_layer, "use_pass_diffuse_indirect", text="Indirect") + col.prop(view_layer, "use_pass_diffuse_color", text="Color") - col = layout.column(align=True) + col = layout.column(heading="Glossy", align=True) + col.prop(view_layer, "use_pass_glossy_direct", text="Direct") + col.prop(view_layer, "use_pass_glossy_indirect", text="Indirect") + col.prop(view_layer, "use_pass_glossy_color", text="Color") + + col = layout.column(heading="Transmission", align=True) + col.prop(view_layer, "use_pass_transmission_direct", text="Direct") + col.prop(view_layer, "use_pass_transmission_indirect", text="Indirect") + col.prop(view_layer, "use_pass_transmission_color", text="Color") + + col = layout.column(heading="Volume", align=True) + col.prop(cycles_view_layer, "use_pass_volume_direct", text="Direct") + col.prop(cycles_view_layer, "use_pass_volume_indirect", text="Indirect") + + col = layout.column(heading="Other", align=True) col.prop(view_layer, "use_pass_emit", text="Emission") col.prop(view_layer, "use_pass_environment") col.prop(view_layer, "use_pass_shadow") @@ -918,11 +892,10 @@ class CYCLES_RENDER_PT_passes_crypto(CyclesButtonsPanel, Panel): cycles_view_layer = context.view_layer.cycles - row = layout.row(align=True) - row.use_property_split = False - row.prop(cycles_view_layer, "use_pass_crypto_object", text="Object", toggle=True) - row.prop(cycles_view_layer, "use_pass_crypto_material", text="Material", toggle=True) - row.prop(cycles_view_layer, "use_pass_crypto_asset", text="Asset", toggle=True) + col = layout.column(heading="Include", align=True) + col.prop(cycles_view_layer, "use_pass_crypto_object", text="Object") + col.prop(cycles_view_layer, "use_pass_crypto_material", text="Material") + col.prop(cycles_view_layer, "use_pass_crypto_asset", text="Asset") layout.prop(cycles_view_layer, "pass_crypto_depth", text="Levels") @@ -1012,10 +985,9 @@ class CYCLES_RENDER_PT_denoising(CyclesButtonsPanel, Panel): view_layer = context.view_layer cycles_view_layer = view_layer.cycles - split = layout.split() - split.active = cycles_view_layer.use_denoising + layout.active = cycles_view_layer.use_denoising - col = split.column(align=True) + col = layout.column() if show_optix_denoising(context): col.prop(cycles_view_layer, "use_optix_denoising") @@ -1026,51 +998,29 @@ class CYCLES_RENDER_PT_denoising(CyclesButtonsPanel, Panel): return col.prop(cycles_view_layer, "denoising_radius", text="Radius") + + col = layout.column() col.prop(cycles_view_layer, "denoising_strength", slider=True, text="Strength") col.prop(cycles_view_layer, "denoising_feature_strength", slider=True, text="Feature Strength") col.prop(cycles_view_layer, "denoising_relative_pca") layout.separator() - split = layout.split(factor=0.5) - split.active = cycles_view_layer.use_denoising or cycles_view_layer.denoising_store_passes - - col = split.column() - col.alignment = 'RIGHT' - col.label(text="Diffuse") + col = layout.column() + col.active = cycles_view_layer.use_denoising or cycles_view_layer.denoising_store_passes - row = split.row(align=True) - row.use_property_split = False + row = col.row(heading="Diffuse", align=True) row.prop(cycles_view_layer, "denoising_diffuse_direct", text="Direct", toggle=True) row.prop(cycles_view_layer, "denoising_diffuse_indirect", text="Indirect", toggle=True) - split = layout.split(factor=0.5) - split.active = cycles_view_layer.use_denoising or cycles_view_layer.denoising_store_passes - - col = split.column() - col.alignment = 'RIGHT' - col.label(text="Glossy") - - row = split.row(align=True) - row.use_property_split = False + row = col.row(heading="Glossy", align=True) row.prop(cycles_view_layer, "denoising_glossy_direct", text="Direct", toggle=True) row.prop(cycles_view_layer, "denoising_glossy_indirect", text="Indirect", toggle=True) - split = layout.split(factor=0.5) - split.active = cycles_view_layer.use_denoising or cycles_view_layer.denoising_store_passes - - col = split.column() - col.alignment = 'RIGHT' - col.label(text="Transmission") - - row = split.row(align=True) - row.use_property_split = False + row = col.row(heading="Transmission", align=True) row.prop(cycles_view_layer, "denoising_transmission_direct", text="Direct", toggle=True) row.prop(cycles_view_layer, "denoising_transmission_indirect", text="Indirect", toggle=True) - split = layout.split(factor=0.5) - split.active = cycles_view_layer.use_denoising or cycles_view_layer.denoising_store_passes - class CYCLES_PT_post_processing(CyclesButtonsPanel, Panel): bl_label = "Post Processing" @@ -1084,7 +1034,7 @@ class CYCLES_PT_post_processing(CyclesButtonsPanel, Panel): rd = context.scene.render - col = layout.column(align=True) + col = layout.column(align=True, heading="Pipeline") col.prop(rd, "use_compositing") col.prop(rd, "use_sequencer") @@ -1273,22 +1223,18 @@ class CYCLES_OBJECT_PT_visibility(CyclesButtonsPanel, Panel): layout = self.layout layout.use_property_split = True - flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False) - layout = self.layout ob = context.object - col = flow.column() - col.prop(ob, "hide_viewport", text="Show in Viewports", invert_checkbox=True, toggle=False) - col = flow.column() - col.prop(ob, "hide_render", text="Show in Renders", invert_checkbox=True, toggle=False) - col = flow.column() - col.prop(ob, "hide_select", text="Selectable", invert_checkbox=True, toggle=False) + layout.prop(ob, "hide_select", text="Selectable", invert_checkbox=True, toggle=False) + + col = layout.column(heading="Show in") + col.prop(ob, "hide_viewport", text="Viewports", invert_checkbox=True, toggle=False) + col.prop(ob, "hide_render", text="Renders", invert_checkbox=True, toggle=False) if has_geometry_visibility(ob): cob = ob.cycles - col = flow.column() + col = layout.column(heading="Mask") col.prop(cob, "is_shadow_catcher") - col = flow.column() col.prop(cob, "is_holdout") @@ -1312,24 +1258,16 @@ class CYCLES_OBJECT_PT_visibility_ray_visibility(CyclesButtonsPanel, Panel): cob = ob.cycles visibility = ob.cycles_visibility - flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False) - - col = flow.column() + col = layout.column() col.prop(visibility, "camera") - col = flow.column() col.prop(visibility, "diffuse") - col = flow.column() col.prop(visibility, "glossy") - col = flow.column() col.prop(visibility, "transmission") - col = flow.column() col.prop(visibility, "scatter") if ob.type != 'LIGHT': - col = flow.column() - col.prop(visibility, "shadow") - - layout.separator() + sub = col.column() + sub.prop(visibility, "shadow") class CYCLES_OBJECT_PT_visibility_culling(CyclesButtonsPanel, Panel): @@ -1352,15 +1290,13 @@ class CYCLES_OBJECT_PT_visibility_culling(CyclesButtonsPanel, Panel): ob = context.object cob = ob.cycles - flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False) - - col = flow.column() - col.active = scene.render.use_simplify and cscene.use_camera_cull - col.prop(cob, "use_camera_cull") + row = layout.row() + row.active = scene.render.use_simplify and cscene.use_camera_cull + row.prop(cob, "use_camera_cull") - col = flow.column() - col.active = scene.render.use_simplify and cscene.use_distance_cull - col.prop(cob, "use_distance_cull") + row = layout.row() + row.active = scene.render.use_simplify and cscene.use_distance_cull + row.prop(cob, "use_distance_cull") def panel_node_draw(layout, id_data, output_type, input_name): @@ -1474,6 +1410,8 @@ class CYCLES_LIGHT_PT_nodes(CyclesButtonsPanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True + light = context.light panel_node_draw(layout, light, 'OUTPUT_LIGHT', 'Surface') @@ -1523,6 +1461,8 @@ class CYCLES_WORLD_PT_surface(CyclesButtonsPanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True + world = context.world if not panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Surface'): @@ -1542,6 +1482,8 @@ class CYCLES_WORLD_PT_volume(CyclesButtonsPanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True + world = context.world panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Volume') @@ -1729,6 +1671,8 @@ class CYCLES_MATERIAL_PT_surface(CyclesButtonsPanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True + mat = context.material if not panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Surface'): layout.prop(mat, "diffuse_color") @@ -1747,6 +1691,8 @@ class CYCLES_MATERIAL_PT_volume(CyclesButtonsPanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True + mat = context.material # cmat = mat.cycles @@ -1765,6 +1711,8 @@ class CYCLES_MATERIAL_PT_displacement(CyclesButtonsPanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True + mat = context.material panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Displacement') @@ -1906,26 +1854,24 @@ class CYCLES_RENDER_PT_bake_influence(CyclesButtonsPanel, Panel): sub.prop(cbk, "normal_b", text="B") elif cscene.bake_type == 'COMBINED': - row = col.row(align=True) - row.use_property_split = False - row.prop(cbk, "use_pass_direct", toggle=True) - row.prop(cbk, "use_pass_indirect", toggle=True) - flow = col.grid_flow(row_major=False, columns=0, even_columns=False, even_rows=False, align=True) + col = layout.column(heading="Lighting", align=True) + col.prop(cbk, "use_pass_direct") + col.prop(cbk, "use_pass_indirect") - flow.active = cbk.use_pass_direct or cbk.use_pass_indirect - flow.prop(cbk, "use_pass_diffuse") - flow.prop(cbk, "use_pass_glossy") - flow.prop(cbk, "use_pass_transmission") - flow.prop(cbk, "use_pass_ambient_occlusion") - flow.prop(cbk, "use_pass_emit") + col = layout.column(heading="Contributions", align=True) + col.active = cbk.use_pass_direct or cbk.use_pass_indirect + col.prop(cbk, "use_pass_diffuse") + col.prop(cbk, "use_pass_glossy") + col.prop(cbk, "use_pass_transmission") + col.prop(cbk, "use_pass_ambient_occlusion") + col.prop(cbk, "use_pass_emit") elif cscene.bake_type in {'DIFFUSE', 'GLOSSY', 'TRANSMISSION'}: - row = col.row(align=True) - row.use_property_split = False - row.prop(cbk, "use_pass_direct", toggle=True) - row.prop(cbk, "use_pass_indirect", toggle=True) - row.prop(cbk, "use_pass_color", toggle=True) + col = layout.column(heading="Contributions", align=True) + col.prop(cbk, "use_pass_direct") + col.prop(cbk, "use_pass_indirect") + col.prop(cbk, "use_pass_color") class CYCLES_RENDER_PT_bake_selected_to_active(CyclesButtonsPanel, Panel): @@ -2131,17 +2077,17 @@ class CYCLES_RENDER_PT_simplify_culling(CyclesButtonsPanel, Panel): layout.active = rd.use_simplify - col = layout.column() - col.prop(cscene, "use_camera_cull") - sub = col.column() + row = layout.row(heading="Camera Culling") + row.prop(cscene, "use_camera_cull", text="") + sub = row.column() sub.active = cscene.use_camera_cull - sub.prop(cscene, "camera_cull_margin") + sub.prop(cscene, "camera_cull_margin", text="") - col = layout.column() - col.prop(cscene, "use_distance_cull") - sub = col.column() + row = layout.row(heading="Distance Culling") + row.prop(cscene, "use_distance_cull", text="") + sub = row.column() sub.active = cscene.use_distance_cull - sub.prop(cscene, "distance_cull_margin", text="Distance") + sub.prop(cscene, "distance_cull_margin", text="") class CYCLES_VIEW3D_PT_shading_render_pass(Panel): diff --git a/intern/dualcon/dualcon.h b/intern/dualcon/dualcon.h index e9bff72a1ce..60cec101545 100644 --- a/intern/dualcon/dualcon.h +++ b/intern/dualcon/dualcon.h @@ -29,7 +29,7 @@ typedef float (*DualConCo)[3]; typedef unsigned int (*DualConTri)[3]; -typedef unsigned int(*DualConLoop); +typedef unsigned int *DualConLoop; typedef struct DualConInput { DualConLoop mloop; diff --git a/intern/dualcon/intern/octree.cpp b/intern/dualcon/intern/octree.cpp index 70b3b8bb457..c9d5639cb5d 100644 --- a/intern/dualcon/intern/octree.cpp +++ b/intern/dualcon/intern/octree.cpp @@ -480,7 +480,7 @@ void Octree::trace() if (chdpath != NULL) { dc_printf("there are incomplete rings.\n"); printPaths(chdpath); - }; + } } Node *Octree::trace(Node *newnode, int *st, int len, int depth, PathList *&paths) diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt index 68fc9637e02..699ac4afe88 100644 --- a/intern/ghost/CMakeLists.txt +++ b/intern/ghost/CMakeLists.txt @@ -21,7 +21,6 @@ set(INC . ../glew-mx - ../string ../../source/blender/imbuf ../../source/blender/makesdna ) @@ -86,7 +85,6 @@ set(SRC set(LIB bf_intern_glew_mx - bf_intern_string ${GLEW_LIBRARY} ) @@ -151,7 +149,7 @@ if(WITH_HEADLESS OR WITH_GHOST_SDL) endif() endif() -elseif(APPLE AND NOT WITH_X11) +elseif(APPLE AND NOT WITH_GHOST_X11) list(APPEND SRC intern/GHOST_DisplayManagerCocoa.mm intern/GHOST_SystemCocoa.mm @@ -179,73 +177,143 @@ elseif(APPLE AND NOT WITH_X11) ) endif() -elseif(WITH_X11) - list(APPEND INC_SYS - ${X11_X11_INCLUDE_PATH} - ) - - list(APPEND SRC - intern/GHOST_DisplayManagerX11.cpp - intern/GHOST_SystemX11.cpp - intern/GHOST_TaskbarX11.cpp - intern/GHOST_WindowX11.cpp - - intern/GHOST_DisplayManagerX11.h - intern/GHOST_IconX11.h - intern/GHOST_SystemX11.h - intern/GHOST_TaskbarX11.h - intern/GHOST_WindowX11.h - ) +elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND) + if(WITH_GHOST_X11) + list(APPEND INC_SYS + ${X11_X11_INCLUDE_PATH} + ) - if(NOT WITH_GL_EGL) list(APPEND SRC - intern/GHOST_ContextGLX.cpp - - intern/GHOST_ContextGLX.h + intern/GHOST_DisplayManagerX11.cpp + intern/GHOST_SystemX11.cpp + intern/GHOST_TaskbarX11.cpp + intern/GHOST_WindowX11.cpp + + intern/GHOST_DisplayManagerX11.h + intern/GHOST_IconX11.h + intern/GHOST_SystemX11.h + intern/GHOST_TaskbarX11.h + intern/GHOST_WindowX11.h ) - endif() - if(WITH_GHOST_XDND) - add_definitions(-DWITH_XDND) + if(NOT WITH_GL_EGL) + list(APPEND SRC + intern/GHOST_ContextGLX.cpp - list(APPEND LIB - extern_xdnd - ) + intern/GHOST_ContextGLX.h + ) + endif() - list(APPEND INC - ../../extern/xdnd - ) + if(WITH_GHOST_XDND) + add_definitions(-DWITH_XDND) - list(APPEND SRC - intern/GHOST_DropTargetX11.cpp + list(APPEND LIB + extern_xdnd + ) - intern/GHOST_DropTargetX11.h - ) + list(APPEND INC + ../../extern/xdnd + ) + + list(APPEND SRC + intern/GHOST_DropTargetX11.cpp + + intern/GHOST_DropTargetX11.h + ) + endif() + + if(X11_XF86keysym_INCLUDE_PATH) + add_definitions(-DWITH_XF86KEYSYM) + list(APPEND INC_SYS + ${X11_XF86keysym_INCLUDE_PATH} + ) + endif() + + if(WITH_X11_XF86VMODE) + add_definitions(-DWITH_X11_XF86VMODE) + list(APPEND INC_SYS + ${X11_xf86vmode_INCLUDE_PATH} + ) + endif() + + if(WITH_X11_XFIXES) + add_definitions(-DWITH_X11_XFIXES) + list(APPEND INC_SYS + ${X11_Xfixes_INCLUDE_PATH} + ) + endif() + + if(WITH_X11_ALPHA) + add_definitions(-DWITH_X11_ALPHA) + endif() + + if(WITH_X11_XINPUT) + add_definitions(-DWITH_X11_XINPUT) + list(APPEND INC_SYS + ${X11_Xinput_INCLUDE_PATH} + ) + endif() + + add_definitions(-DWITH_GHOST_X11) endif() - if(X11_XF86keysym_INCLUDE_PATH) - add_definitions(-DWITH_XF86KEYSYM) + if(WITH_GHOST_WAYLAND) list(APPEND INC_SYS - ${X11_XF86keysym_INCLUDE_PATH} + ${wayland-client_INCLUDE_DIRS} + ${wayland-egl_INCLUDE_DIRS} + ${xkbcommon_INCLUDE_DIRS} + ${wayland-cursor_INCLUDE_DIRS} ) - endif() - if(WITH_X11_XF86VMODE) - add_definitions(-DWITH_X11_XF86VMODE) - list(APPEND INC_SYS - ${X11_xf86vmode_INCLUDE_PATH} + list(APPEND SRC + intern/GHOST_SystemWayland.cpp + intern/GHOST_WindowWayland.cpp + + intern/GHOST_SystemWayland.h + intern/GHOST_WindowWayland.h ) - endif() - if(WITH_X11_XFIXES) - add_definitions(-DWITH_X11_XFIXES) + pkg_get_variable(WAYLAND_SCANNER wayland-scanner wayland_scanner) + pkg_get_variable(WAYLAND_PROTOCOLS_DIR wayland-protocols pkgdatadir) + + # Generate protocols bindings. + macro(generate_protocol_bindings NAME PROT_DEF) + add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${NAME}-client-protocol.h + COMMAND ${WAYLAND_SCANNER} client-header ${PROT_DEF} ${NAME}-client-protocol.h + ) + add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${NAME}-client-protocol.c + COMMAND ${WAYLAND_SCANNER} private-code ${PROT_DEF} ${NAME}-client-protocol.c + DEPENDS ${NAME}-client-protocol.h + ) + list(APPEND SRC + ${CMAKE_CURRENT_BINARY_DIR}/${NAME}-client-protocol.c + ${CMAKE_CURRENT_BINARY_DIR}/${NAME}-client-protocol.h + ) + endmacro() + list(APPEND INC_SYS - ${X11_Xfixes_INCLUDE_PATH} + ${CMAKE_CURRENT_BINARY_DIR} + ) + + # xdg-shell. + generate_protocol_bindings( + xdg-shell + "${WAYLAND_PROTOCOLS_DIR}/stable/xdg-shell/xdg-shell.xml" + ) + # Pointer-constraints. + generate_protocol_bindings( + pointer-constraints + "${WAYLAND_PROTOCOLS_DIR}/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml" + ) + # Relative-pointer. + generate_protocol_bindings( + relative-pointer + "${WAYLAND_PROTOCOLS_DIR}/unstable/relative-pointer/relative-pointer-unstable-v1.xml" ) - endif() - if(WITH_X11_ALPHA) - add_definitions(-DWITH_X11_ALPHA) + add_definitions(-DWITH_GHOST_WAYLAND) endif() if(WITH_INPUT_NDOF) @@ -260,14 +328,6 @@ elseif(WITH_X11) add_definitions(-DPREFIX="${CMAKE_INSTALL_PREFIX}") endif() - if(WITH_X11_XINPUT) - add_definitions(-DWITH_X11_XINPUT) - list(APPEND INC_SYS - ${X11_Xinput_INCLUDE_PATH} - ) - endif() - - add_definitions(-DWITH_X11) elseif(WIN32) # # Warnings as errors, this is too strict! diff --git a/intern/ghost/GHOST_IContext.h b/intern/ghost/GHOST_IContext.h index 1225262a908..8c24261644a 100644 --- a/intern/ghost/GHOST_IContext.h +++ b/intern/ghost/GHOST_IContext.h @@ -26,7 +26,6 @@ #define __GHOST_IContext_H__ #include "GHOST_Types.h" -#include "STR_String.h" /** * Interface for GHOST context. diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h index 58d1a08da74..9b619f5c684 100644 --- a/intern/ghost/GHOST_ISystem.h +++ b/intern/ghost/GHOST_ISystem.h @@ -27,6 +27,8 @@ #ifndef __GHOST_ISYSTEM_H__ #define __GHOST_ISYSTEM_H__ +#include <stdlib.h> + #include "GHOST_IContext.h" #include "GHOST_ITimerTask.h" #include "GHOST_IWindow.h" @@ -240,7 +242,7 @@ class GHOST_ISystem { * \param parentWindow: Parent (embedder) window * \return The new window (or 0 if creation failed). */ - virtual GHOST_IWindow *createWindow(const STR_String &title, + virtual GHOST_IWindow *createWindow(const char *title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, diff --git a/intern/ghost/GHOST_IWindow.h b/intern/ghost/GHOST_IWindow.h index daf07b81e01..62290d20f1c 100644 --- a/intern/ghost/GHOST_IWindow.h +++ b/intern/ghost/GHOST_IWindow.h @@ -27,7 +27,9 @@ #include "GHOST_Rect.h" #include "GHOST_Types.h" -#include "STR_String.h" + +#include <stdlib.h> +#include <string> /** * Interface for GHOST windows. @@ -81,13 +83,13 @@ class GHOST_IWindow { * Sets the title displayed in the title bar. * \param title The title to display in the title bar. */ - virtual void setTitle(const STR_String &title) = 0; + virtual void setTitle(const char *title) = 0; /** * Returns the title displayed in the title bar. * \param title The title displayed in the title bar. */ - virtual void getTitle(STR_String &title) const = 0; + virtual std::string getTitle() const = 0; /** * Returns the window rectangle dimensions. diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp index db9fd2e3bf9..843684b6d2e 100644 --- a/intern/ghost/intern/GHOST_C-api.cpp +++ b/intern/ghost/intern/GHOST_C-api.cpp @@ -24,6 +24,7 @@ */ #include <stdlib.h> +#include <string.h> #include "GHOST_C-api.h" #include "GHOST_IEvent.h" @@ -527,17 +528,15 @@ void GHOST_SetTitle(GHOST_WindowHandle windowhandle, const char *title) char *GHOST_GetTitle(GHOST_WindowHandle windowhandle) { GHOST_IWindow *window = (GHOST_IWindow *)windowhandle; - STR_String title; + std::string title = window->getTitle(); - window->getTitle(title); - - char *ctitle = (char *)malloc(title.Length() + 1); + char *ctitle = (char *)malloc(title.size() + 1); if (ctitle == NULL) { return NULL; } - strcpy(ctitle, title.Ptr()); + strcpy(ctitle, title.c_str()); return ctitle; } @@ -678,7 +677,7 @@ GHOST_TSuccess GHOST_ActivateOpenGLContext(GHOST_ContextHandle contexthandle) return context->activateDrawingContext(); } else { - GHOST_PRINT("GHOST_ActivateOpenGLContext: Context not valid"); + GHOST_PRINTF("%s: Context not valid\n", __func__); return GHOST_kFailure; } } diff --git a/intern/ghost/intern/GHOST_Debug.h b/intern/ghost/intern/GHOST_Debug.h index 0163197e14a..5b5c2688297 100644 --- a/intern/ghost/intern/GHOST_Debug.h +++ b/intern/ghost/intern/GHOST_Debug.h @@ -33,15 +33,11 @@ #endif #ifdef WITH_GHOST_DEBUG -# define GHOST_DEBUG // spit ghost events to stdout -#endif // WITH_GHOST_DEBUG - -#ifdef GHOST_DEBUG # include <iostream> # include <stdio.h> //for printf() -#endif // GHOST_DEBUG +#endif // WITH_GHOST_DEBUG -#ifdef GHOST_DEBUG +#ifdef WITH_GHOST_DEBUG # define GHOST_PRINT(x) \ { \ std::cout << x; \ @@ -52,10 +48,10 @@ printf(x, __VA_ARGS__); \ } \ (void)0 -#else // GHOST_DEBUG +#else // WITH_GHOST_DEBUG # define GHOST_PRINT(x) # define GHOST_PRINTF(x, ...) -#endif // GHOST_DEBUG +#endif // WITH_GHOST_DEBUG #ifdef WITH_ASSERT_ABORT # include <stdio.h> //for fprintf() @@ -70,7 +66,7 @@ } \ } \ (void)0 -#elif defined(GHOST_DEBUG) +#elif defined(WITH_GHOST_DEBUG) # define GHOST_ASSERT(x, info) \ { \ if (!(x)) { \ @@ -80,8 +76,8 @@ } \ } \ (void)0 -#else // GHOST_DEBUG +#else // WITH_GHOST_DEBUG # define GHOST_ASSERT(x, info) ((void)0) -#endif // GHOST_DEBUG +#endif // WITH_GHOST_DEBUG #endif // __GHOST_DEBUG_H__ diff --git a/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp b/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp index aabaffc7732..3557c4cd0c5 100644 --- a/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp +++ b/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp @@ -80,13 +80,13 @@ GHOST_TSuccess GHOST_DisplayManagerWin32::getDisplaySetting(GHOST_TUns8 display, GHOST_TSuccess success; DEVMODE dm; if (::EnumDisplaySettings(display_device.DeviceName, index, &dm)) { -#ifdef GHOST_DEBUG +#ifdef WITH_GHOST_DEBUG printf("display mode: width=%d, height=%d, bpp=%d, frequency=%d\n", dm.dmPelsWidth, dm.dmPelsHeight, dm.dmBitsPerPel, dm.dmDisplayFrequency); -#endif // GHOST_DEBUG +#endif // WITH_GHOST_DEBUG setting.xPixels = dm.dmPelsWidth; setting.yPixels = dm.dmPelsHeight; setting.bpp = dm.dmBitsPerPel; @@ -142,16 +142,16 @@ GHOST_TSuccess GHOST_DisplayManagerWin32::setCurrentDisplaySetting( * dm.dmSize = sizeof(DEVMODE); * dm.dmDriverExtra = 0; */ -#ifdef GHOST_DEBUG +#ifdef WITH_GHOST_DEBUG printf("display change: Requested settings:\n"); printf(" dmBitsPerPel=%d\n", dm.dmBitsPerPel); printf(" dmPelsWidth=%d\n", dm.dmPelsWidth); printf(" dmPelsHeight=%d\n", dm.dmPelsHeight); printf(" dmDisplayFrequency=%d\n", dm.dmDisplayFrequency); -#endif // GHOST_DEBUG +#endif // WITH_GHOST_DEBUG LONG status = ::ChangeDisplaySettings(&dm, CDS_FULLSCREEN); -#ifdef GHOST_DEBUG +#ifdef WITH_GHOST_DEBUG switch (status) { case DISP_CHANGE_SUCCESSFUL: printf("display change: The settings change was successful.\n"); @@ -182,6 +182,6 @@ GHOST_TSuccess GHOST_DisplayManagerWin32::setCurrentDisplaySetting( printf("display change: Return value invalid\n"); break; } -#endif // GHOST_DEBUG +#endif // WITH_GHOST_DEBUG return status == DISP_CHANGE_SUCCESSFUL ? GHOST_kSuccess : GHOST_kFailure; } diff --git a/intern/ghost/intern/GHOST_DropTargetWin32.cpp b/intern/ghost/intern/GHOST_DropTargetWin32.cpp index 9f8ce3b5095..fe11d9a28f2 100644 --- a/intern/ghost/intern/GHOST_DropTargetWin32.cpp +++ b/intern/ghost/intern/GHOST_DropTargetWin32.cpp @@ -28,10 +28,10 @@ #include "utf_winfunc.h" #include "utfconv.h" -#ifdef GHOST_DEBUG +#ifdef WITH_GHOST_DEBUG // utility void printLastError(void); -#endif // GHOST_DEBUG +#endif // WITH_GHOST_DEBUG GHOST_DropTargetWin32::GHOST_DropTargetWin32(GHOST_WindowWin32 *window, GHOST_SystemWin32 *system) : m_window(window), m_system(system) @@ -209,9 +209,9 @@ void *GHOST_DropTargetWin32::getGhostData(IDataObject *pDataObject) // return getDropDataAsBitmap(pDataObject); break; default: -#ifdef GHOST_DEBUG +#ifdef WITH_GHOST_DEBUG ::printf("\nGHOST_kDragnDropTypeUnknown"); -#endif // GHOST_DEBUG +#endif // WITH_GHOST_DEBUG return NULL; break; } @@ -284,10 +284,10 @@ void *GHOST_DropTargetWin32::getDropDataAsString(IDataObject *pDataObject) // Free memory ::GlobalUnlock(stgmed.hGlobal); ::ReleaseStgMedium(&stgmed); -#ifdef GHOST_DEBUG +#ifdef WITH_GHOST_DEBUG ::printf("\n<converted droped unicode string>\n%s\n</droped converted unicode string>\n", tmp_string); -#endif // GHOST_DEBUG +#endif // WITH_GHOST_DEBUG return tmp_string; } } @@ -336,9 +336,9 @@ int GHOST_DropTargetWin32::WideCharToANSI(LPCWSTR in, char *&out) NULL); if (!size) { -#ifdef GHOST_DEBUG +#ifdef WITH_GHOST_DEBUG ::printLastError(); -#endif // GHOST_DEBUG +#endif // WITH_GHOST_DEBUG return 0; } @@ -351,16 +351,16 @@ int GHOST_DropTargetWin32::WideCharToANSI(LPCWSTR in, char *&out) size = ::WideCharToMultiByte(CP_ACP, 0x00000400, in, -1, (LPSTR)out, size, NULL, NULL); if (!size) { -#ifdef GHOST_DEBUG +#ifdef WITH_GHOST_DEBUG ::printLastError(); -#endif // GHOST_DEBUG +#endif // WITH_GHOST_DEBUG ::free(out); out = NULL; } return size; } -#ifdef GHOST_DEBUG +#ifdef WITH_GHOST_DEBUG void printLastError(void) { LPTSTR s; @@ -378,4 +378,4 @@ void printLastError(void) LocalFree(s); } } -#endif // GHOST_DEBUG +#endif // WITH_GHOST_DEBUG diff --git a/intern/ghost/intern/GHOST_EventKey.h b/intern/ghost/intern/GHOST_EventKey.h index 24e20b20659..8f59c555914 100644 --- a/intern/ghost/intern/GHOST_EventKey.h +++ b/intern/ghost/intern/GHOST_EventKey.h @@ -25,6 +25,8 @@ #ifndef __GHOST_EVENTKEY_H__ #define __GHOST_EVENTKEY_H__ +#include <string.h> + #include "GHOST_Event.h" /** diff --git a/intern/ghost/intern/GHOST_EventPrinter.h b/intern/ghost/intern/GHOST_EventPrinter.h index fad9ec3cc69..ead16525ec6 100644 --- a/intern/ghost/intern/GHOST_EventPrinter.h +++ b/intern/ghost/intern/GHOST_EventPrinter.h @@ -27,8 +27,6 @@ #include "GHOST_IEventConsumer.h" -#include "STR_String.h" - /** * An Event consumer that prints all the events to standard out. * Really useful when debugging. diff --git a/intern/ghost/intern/GHOST_ISystem.cpp b/intern/ghost/intern/GHOST_ISystem.cpp index 914f6712676..7c12bfe0306 100644 --- a/intern/ghost/intern/GHOST_ISystem.cpp +++ b/intern/ghost/intern/GHOST_ISystem.cpp @@ -27,20 +27,22 @@ #include "GHOST_ISystem.h" -#ifdef WITH_X11 +#if defined(WITH_HEADLESS) +# include "GHOST_SystemNULL.h" +#elif defined(WITH_GHOST_X11) && defined(WITH_GHOST_WAYLAND) +# include "GHOST_SystemWayland.h" # include "GHOST_SystemX11.h" -#else -# ifdef WITH_HEADLESS -# include "GHOST_SystemNULL.h" -# elif defined(WITH_GHOST_SDL) -# include "GHOST_SystemSDL.h" -# elif defined(WIN32) -# include "GHOST_SystemWin32.h" -# else -# ifdef __APPLE__ -# include "GHOST_SystemCocoa.h" -# endif -# endif +# include <stdexcept> +#elif defined(WITH_GHOST_X11) +# include "GHOST_SystemX11.h" +#elif defined(WITH_GHOST_WAYLAND) +# include "GHOST_SystemWayland.h" +#elif defined(WITH_GHOST_SDL) +# include "GHOST_SystemSDL.h" +#elif defined(WIN32) +# include "GHOST_SystemWin32.h" +#elif defined(__APPLE__) +# include "GHOST_SystemCocoa.h" #endif GHOST_ISystem *GHOST_ISystem::m_system = NULL; @@ -49,20 +51,29 @@ GHOST_TSuccess GHOST_ISystem::createSystem() { GHOST_TSuccess success; if (!m_system) { -#ifdef WITH_X11 - m_system = new GHOST_SystemX11(); -#else -# ifdef WITH_HEADLESS +#if defined(WITH_HEADLESS) m_system = new GHOST_SystemNULL(); -# elif defined(WITH_GHOST_SDL) +#elif defined(WITH_GHOST_X11) && defined(WITH_GHOST_WAYLAND) + /* Special case, try Wayland, fall back to X11. */ + try { + m_system = new GHOST_SystemWayland(); + } + catch (const std::runtime_error &) { + /* fallback to X11. */ + } + if (!m_system) { + m_system = new GHOST_SystemX11(); + } +#elif defined(WITH_GHOST_X11) + m_system = new GHOST_SystemX11(); +#elif defined(WITH_GHOST_WAYLAND) + m_system = new GHOST_SystemWayland(); +#elif defined(WITH_GHOST_SDL) m_system = new GHOST_SystemSDL(); -# elif defined(WIN32) +#elif defined(WIN32) m_system = new GHOST_SystemWin32(); -# else -# ifdef __APPLE__ +#elif defined(__APPLE__) m_system = new GHOST_SystemCocoa(); -# endif -# endif #endif success = m_system != NULL ? GHOST_kSuccess : GHOST_kFailure; } diff --git a/intern/ghost/intern/GHOST_IXrGraphicsBinding.h b/intern/ghost/intern/GHOST_IXrGraphicsBinding.h index cddb557d163..5794a682023 100644 --- a/intern/ghost/intern/GHOST_IXrGraphicsBinding.h +++ b/intern/ghost/intern/GHOST_IXrGraphicsBinding.h @@ -33,7 +33,7 @@ class GHOST_IXrGraphicsBinding { public: union { -#if defined(WITH_X11) +#if defined(WITH_GHOST_X11) XrGraphicsBindingOpenGLXlibKHR glx; #elif defined(WIN32) XrGraphicsBindingOpenGLWin32KHR wgl; diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index a9fbadab37a..dda78c0ac5b 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -19,6 +19,8 @@ #include "GHOST_EventKey.h" #include "GHOST_EventNDOF.h" #include "GHOST_WindowManager.h" + +#include <limits.h> #include <math.h> #include <stdio.h> // for error/info reporting #include <string.h> // for memory functions diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp index 85eb6d58679..587e4c28102 100644 --- a/intern/ghost/intern/GHOST_System.cpp +++ b/intern/ghost/intern/GHOST_System.cpp @@ -309,12 +309,12 @@ GHOST_TSuccess GHOST_System::init() m_windowManager = new GHOST_WindowManager(); m_eventManager = new GHOST_EventManager(); -#ifdef GHOST_DEBUG +#ifdef WITH_GHOST_DEBUG if (m_eventManager) { m_eventPrinter = new GHOST_EventPrinter(); m_eventManager->addConsumer(m_eventPrinter); } -#endif // GHOST_DEBUG +#endif // WITH_GHOST_DEBUG if (m_timerManager && m_windowManager && m_eventManager) { return GHOST_kSuccess; @@ -367,7 +367,7 @@ GHOST_TSuccess GHOST_System::createFullScreenWindow(GHOST_Window **window, GHOST_ASSERT(m_displayManager, "GHOST_System::createFullScreenWindow(): invalid display manager"); // GHOST_PRINT("GHOST_System::createFullScreenWindow(): creating full-screen window\n"); - *window = (GHOST_Window *)createWindow(STR_String(""), + *window = (GHOST_Window *)createWindow("", 0, 0, settings.xPixels, diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h index eaaa2ff6ee6..0f58be49dff 100644 --- a/intern/ghost/intern/GHOST_System.h +++ b/intern/ghost/intern/GHOST_System.h @@ -31,9 +31,9 @@ #include "GHOST_Debug.h" #include "GHOST_EventManager.h" #include "GHOST_ModifierKeys.h" -#ifdef GHOST_DEBUG +#ifdef WITH_GHOST_DEBUG # include "GHOST_EventPrinter.h" -#endif // GHOST_DEBUG +#endif // WITH_GHOST_DEBUG class GHOST_DisplayManager; class GHOST_Event; @@ -390,9 +390,9 @@ class GHOST_System : public GHOST_ISystem { #endif /** Prints all the events. */ -#ifdef GHOST_DEBUG +#ifdef WITH_GHOST_DEBUG GHOST_EventPrinter *m_eventPrinter; -#endif // GHOST_DEBUG +#endif // WITH_GHOST_DEBUG /** Settings of the display before the display went fullscreen. */ GHOST_DisplaySetting m_preFullScreenSetting; diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h index 1e44c3e31d4..d058697470a 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.h +++ b/intern/ghost/intern/GHOST_SystemCocoa.h @@ -100,7 +100,7 @@ class GHOST_SystemCocoa : public GHOST_System { * \param parentWindow Parent (embedder) window * \return The new window (or 0 if creation failed). */ - GHOST_IWindow *createWindow(const STR_String &title, + GHOST_IWindow *createWindow(const char *title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index 3d6d187587c..2b6a2902757 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -698,7 +698,7 @@ void GHOST_SystemCocoa::getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns3 getMainDisplayDimensions(width, height); } -GHOST_IWindow *GHOST_SystemCocoa::createWindow(const STR_String &title, +GHOST_IWindow *GHOST_SystemCocoa::createWindow(const char *title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, diff --git a/intern/ghost/intern/GHOST_SystemNULL.h b/intern/ghost/intern/GHOST_SystemNULL.h index 68a726f2be8..186cb92d1aa 100644 --- a/intern/ghost/intern/GHOST_SystemNULL.h +++ b/intern/ghost/intern/GHOST_SystemNULL.h @@ -106,7 +106,7 @@ class GHOST_SystemNULL : public GHOST_System { return GHOST_kFailure; } - GHOST_IWindow *createWindow(const STR_String &title, + GHOST_IWindow *createWindow(const char *title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, diff --git a/intern/ghost/intern/GHOST_SystemSDL.cpp b/intern/ghost/intern/GHOST_SystemSDL.cpp index 97a75d7a0f5..b32ec4306e8 100644 --- a/intern/ghost/intern/GHOST_SystemSDL.cpp +++ b/intern/ghost/intern/GHOST_SystemSDL.cpp @@ -49,7 +49,7 @@ GHOST_SystemSDL::~GHOST_SystemSDL() SDL_Quit(); } -GHOST_IWindow *GHOST_SystemSDL::createWindow(const STR_String &title, +GHOST_IWindow *GHOST_SystemSDL::createWindow(const char *title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, diff --git a/intern/ghost/intern/GHOST_SystemSDL.h b/intern/ghost/intern/GHOST_SystemSDL.h index 1994781530b..8feec9de61d 100644 --- a/intern/ghost/intern/GHOST_SystemSDL.h +++ b/intern/ghost/intern/GHOST_SystemSDL.h @@ -80,7 +80,7 @@ class GHOST_SystemSDL : public GHOST_System { private: GHOST_TSuccess init(); - GHOST_IWindow *createWindow(const STR_String &title, + GHOST_IWindow *createWindow(const char *title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp new file mode 100644 index 00000000000..666515ed088 --- /dev/null +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -0,0 +1,1654 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup GHOST + */ + +#include "GHOST_SystemWayland.h" +#include "GHOST_Event.h" +#include "GHOST_EventButton.h" +#include "GHOST_EventCursor.h" +#include "GHOST_EventDragnDrop.h" +#include "GHOST_EventKey.h" +#include "GHOST_EventWheel.h" +#include "GHOST_WindowManager.h" + +#include "GHOST_ContextEGL.h" + +#include <EGL/egl.h> +#include <wayland-egl.h> + +#include <algorithm> +#include <atomic> +#include <exception> +#include <thread> +#include <unordered_map> +#include <unordered_set> + +#include <pointer-constraints-client-protocol.h> +#include <relative-pointer-client-protocol.h> +#include <wayland-cursor.h> +#include <xkbcommon/xkbcommon.h> + +#include <fcntl.h> +#include <linux/input-event-codes.h> +#include <sys/mman.h> +#include <unistd.h> + +#include <cstring> + +struct output_t { + struct wl_output *output; + int32_t width, height; + int transform; + int scale; + std::string make; + std::string model; +}; + +struct buffer_t { + void *data; + size_t size; +}; + +struct cursor_t { + bool visible; + struct wl_surface *surface = nullptr; + struct wl_buffer *buffer; + struct wl_cursor_image image; + struct buffer_t *file_buffer = nullptr; +}; + +struct data_offer_t { + std::unordered_set<std::string> types; + uint32_t source_actions; + uint32_t dnd_action; + struct wl_data_offer *id; + std::atomic<bool> in_use; + struct { + int x, y; + } dnd; +}; + +struct data_source_t { + struct wl_data_source *data_source; + /** Last device that was active. */ + uint32_t source_serial; + char *buffer_out; +}; + +struct input_t { + GHOST_SystemWayland *system; + + std::string name; + struct wl_seat *seat; + struct wl_pointer *pointer = nullptr; + struct wl_keyboard *keyboard = nullptr; + + uint32_t pointer_serial; + int x, y; + GHOST_Buttons buttons; + struct cursor_t cursor; + + struct zwp_relative_pointer_v1 *relative_pointer; + struct zwp_locked_pointer_v1 *locked_pointer; + + struct xkb_context *xkb_context; + struct xkb_state *xkb_state; + + struct wl_data_device *data_device = nullptr; + struct data_offer_t *data_offer_dnd; /* Drag & Drop. */ + struct data_offer_t *data_offer_copy_paste; /* Copy & Paste. */ + + struct data_source_t *data_source; +}; + +struct display_t { + GHOST_SystemWayland *system; + + struct wl_display *display; + struct wl_registry *registry; + struct wl_compositor *compositor = nullptr; + struct xdg_wm_base *xdg_shell = nullptr; + struct wl_shm *shm = nullptr; + std::vector<output_t *> outputs; + std::vector<input_t *> inputs; + struct wl_cursor_theme *cursor_theme = nullptr; + struct wl_data_device_manager *data_device_manager = nullptr; + struct zwp_relative_pointer_manager_v1 *relative_pointer_manager = nullptr; + struct zwp_pointer_constraints_v1 *pointer_constraints = nullptr; + + std::vector<struct wl_surface *> os_surfaces; + std::vector<struct wl_egl_window *> os_egl_windows; +}; + +static void display_destroy(display_t *d) +{ + if (d->data_device_manager) { + wl_data_device_manager_destroy(d->data_device_manager); + } + + for (output_t *output : d->outputs) { + wl_output_destroy(output->output); + delete output; + } + + for (input_t *input : d->inputs) { + if (input->data_source) { + free(input->data_source->buffer_out); + if (input->data_source->data_source) { + wl_data_source_destroy(input->data_source->data_source); + } + delete input->data_source; + } + if (input->data_offer_copy_paste) { + wl_data_offer_destroy(input->data_offer_copy_paste->id); + delete input->data_offer_copy_paste; + } + if (input->data_device) { + wl_data_device_release(input->data_device); + } + if (input->pointer) { + if (input->cursor.file_buffer) { + munmap(input->cursor.file_buffer->data, input->cursor.file_buffer->size); + delete input->cursor.file_buffer; + } + if (input->cursor.surface) { + wl_surface_destroy(input->cursor.surface); + } + if (input->pointer) { + wl_pointer_destroy(input->pointer); + } + } + if (input->keyboard) { + wl_keyboard_destroy(input->keyboard); + } + if (input->xkb_state) { + xkb_state_unref(input->xkb_state); + } + if (input->xkb_context) { + xkb_context_unref(input->xkb_context); + } + wl_seat_destroy(input->seat); + delete input; + } + + if (d->cursor_theme) { + wl_cursor_theme_destroy(d->cursor_theme); + } + + if (d->shm) { + wl_shm_destroy(d->shm); + } + + if (d->relative_pointer_manager) { + zwp_relative_pointer_manager_v1_destroy(d->relative_pointer_manager); + } + + if (d->pointer_constraints) { + zwp_pointer_constraints_v1_destroy(d->pointer_constraints); + } + + for (wl_egl_window *os_egl_window : d->os_egl_windows) { + wl_egl_window_destroy(os_egl_window); + } + + for (wl_surface *os_surface : d->os_surfaces) { + wl_surface_destroy(os_surface); + } + + if (d->compositor) { + wl_compositor_destroy(d->compositor); + } + + if (d->xdg_shell) { + xdg_wm_base_destroy(d->xdg_shell); + } + + if (eglGetDisplay) { + ::eglTerminate(eglGetDisplay(EGLNativeDisplayType(d->display))); + } + + if (d->display) { + wl_display_disconnect(d->display); + } + + delete d; +} + +static GHOST_TKey xkb_map_gkey(const xkb_keysym_t &sym) +{ + + GHOST_TKey gkey; + if (sym >= XKB_KEY_0 && sym <= XKB_KEY_9) { + gkey = GHOST_TKey(sym); + } + else if (sym >= XKB_KEY_KP_0 && sym <= XKB_KEY_KP_9) { + gkey = GHOST_TKey(GHOST_kKeyNumpad0 + sym - XKB_KEY_KP_0); + } + else if (sym >= XKB_KEY_A && sym <= XKB_KEY_Z) { + gkey = GHOST_TKey(sym); + } + else if (sym >= XKB_KEY_a && sym <= XKB_KEY_z) { + gkey = GHOST_TKey(sym - XKB_KEY_a + XKB_KEY_A); + } + else if (sym >= XKB_KEY_F1 && sym <= XKB_KEY_F24) { + gkey = GHOST_TKey(GHOST_kKeyF1 + sym - XKB_KEY_F1); + } + else { + +#define GXMAP(k, x, y) \ + case x: \ + k = y; \ + break + + switch (sym) { + GXMAP(gkey, XKB_KEY_BackSpace, GHOST_kKeyBackSpace); + GXMAP(gkey, XKB_KEY_Tab, GHOST_kKeyTab); + GXMAP(gkey, XKB_KEY_Linefeed, GHOST_kKeyLinefeed); + GXMAP(gkey, XKB_KEY_Clear, GHOST_kKeyClear); + GXMAP(gkey, XKB_KEY_Return, GHOST_kKeyEnter); + + GXMAP(gkey, XKB_KEY_Escape, GHOST_kKeyEsc); + GXMAP(gkey, XKB_KEY_space, GHOST_kKeySpace); + GXMAP(gkey, XKB_KEY_comma, GHOST_kKeyComma); + GXMAP(gkey, XKB_KEY_minus, GHOST_kKeyMinus); + GXMAP(gkey, XKB_KEY_plus, GHOST_kKeyPlus); + GXMAP(gkey, XKB_KEY_period, GHOST_kKeyPeriod); + GXMAP(gkey, XKB_KEY_slash, GHOST_kKeySlash); + + GXMAP(gkey, XKB_KEY_semicolon, GHOST_kKeySemicolon); + GXMAP(gkey, XKB_KEY_equal, GHOST_kKeyEqual); + + GXMAP(gkey, XKB_KEY_bracketleft, GHOST_kKeyLeftBracket); + GXMAP(gkey, XKB_KEY_bracketright, GHOST_kKeyRightBracket); + GXMAP(gkey, XKB_KEY_backslash, GHOST_kKeyBackslash); + GXMAP(gkey, XKB_KEY_grave, GHOST_kKeyAccentGrave); + + GXMAP(gkey, XKB_KEY_Shift_L, GHOST_kKeyLeftShift); + GXMAP(gkey, XKB_KEY_Shift_R, GHOST_kKeyRightShift); + GXMAP(gkey, XKB_KEY_Control_L, GHOST_kKeyLeftControl); + GXMAP(gkey, XKB_KEY_Control_R, GHOST_kKeyRightControl); + GXMAP(gkey, XKB_KEY_Alt_L, GHOST_kKeyLeftAlt); + GXMAP(gkey, XKB_KEY_Alt_R, GHOST_kKeyRightAlt); + GXMAP(gkey, XKB_KEY_Super_L, GHOST_kKeyOS); + GXMAP(gkey, XKB_KEY_Super_R, GHOST_kKeyOS); + GXMAP(gkey, XKB_KEY_Menu, GHOST_kKeyApp); + + GXMAP(gkey, XKB_KEY_Caps_Lock, GHOST_kKeyCapsLock); + GXMAP(gkey, XKB_KEY_Num_Lock, GHOST_kKeyNumLock); + GXMAP(gkey, XKB_KEY_Scroll_Lock, GHOST_kKeyScrollLock); + + GXMAP(gkey, XKB_KEY_Left, GHOST_kKeyLeftArrow); + GXMAP(gkey, XKB_KEY_KP_Left, GHOST_kKeyLeftArrow); + GXMAP(gkey, XKB_KEY_Right, GHOST_kKeyRightArrow); + GXMAP(gkey, XKB_KEY_KP_Right, GHOST_kKeyRightArrow); + GXMAP(gkey, XKB_KEY_Up, GHOST_kKeyUpArrow); + GXMAP(gkey, XKB_KEY_KP_Up, GHOST_kKeyUpArrow); + GXMAP(gkey, XKB_KEY_Down, GHOST_kKeyDownArrow); + GXMAP(gkey, XKB_KEY_KP_Down, GHOST_kKeyDownArrow); + + GXMAP(gkey, XKB_KEY_Print, GHOST_kKeyPrintScreen); + GXMAP(gkey, XKB_KEY_Pause, GHOST_kKeyPause); + + GXMAP(gkey, XKB_KEY_Insert, GHOST_kKeyInsert); + GXMAP(gkey, XKB_KEY_KP_Insert, GHOST_kKeyInsert); + GXMAP(gkey, XKB_KEY_Delete, GHOST_kKeyDelete); + GXMAP(gkey, XKB_KEY_KP_Delete, GHOST_kKeyDelete); + GXMAP(gkey, XKB_KEY_Home, GHOST_kKeyHome); + GXMAP(gkey, XKB_KEY_KP_Home, GHOST_kKeyHome); + GXMAP(gkey, XKB_KEY_End, GHOST_kKeyEnd); + GXMAP(gkey, XKB_KEY_KP_End, GHOST_kKeyEnd); + GXMAP(gkey, XKB_KEY_Page_Up, GHOST_kKeyUpPage); + GXMAP(gkey, XKB_KEY_KP_Page_Up, GHOST_kKeyUpPage); + GXMAP(gkey, XKB_KEY_Page_Down, GHOST_kKeyDownPage); + GXMAP(gkey, XKB_KEY_KP_Page_Down, GHOST_kKeyDownPage); + + GXMAP(gkey, XKB_KEY_KP_Decimal, GHOST_kKeyNumpadPeriod); + GXMAP(gkey, XKB_KEY_KP_Enter, GHOST_kKeyNumpadEnter); + GXMAP(gkey, XKB_KEY_KP_Add, GHOST_kKeyNumpadPlus); + GXMAP(gkey, XKB_KEY_KP_Subtract, GHOST_kKeyNumpadMinus); + GXMAP(gkey, XKB_KEY_KP_Multiply, GHOST_kKeyNumpadAsterisk); + GXMAP(gkey, XKB_KEY_KP_Divide, GHOST_kKeyNumpadSlash); + + GXMAP(gkey, XKB_KEY_XF86AudioPlay, GHOST_kKeyMediaPlay); + GXMAP(gkey, XKB_KEY_XF86AudioStop, GHOST_kKeyMediaStop); + GXMAP(gkey, XKB_KEY_XF86AudioPrev, GHOST_kKeyMediaFirst); + GXMAP(gkey, XKB_KEY_XF86AudioNext, GHOST_kKeyMediaLast); + default: + GHOST_PRINT("unhandled key: " << sym << std::endl); + gkey = GHOST_kKeyUnknown; + } +#undef GXMAP + } + + return gkey; +} + +static const int default_cursor_size = 24; + +static const std::unordered_map<GHOST_TStandardCursor, std::string> cursors = { + {GHOST_kStandardCursorDefault, "left_ptr"}, + {GHOST_kStandardCursorRightArrow, "right_ptr"}, + {GHOST_kStandardCursorLeftArrow, "left_ptr"}, + {GHOST_kStandardCursorInfo, ""}, + {GHOST_kStandardCursorDestroy, ""}, + {GHOST_kStandardCursorHelp, "question_arrow"}, + {GHOST_kStandardCursorWait, "watch"}, + {GHOST_kStandardCursorText, "xterm"}, + {GHOST_kStandardCursorCrosshair, "crosshair"}, + {GHOST_kStandardCursorCrosshairA, ""}, + {GHOST_kStandardCursorCrosshairB, ""}, + {GHOST_kStandardCursorCrosshairC, ""}, + {GHOST_kStandardCursorPencil, ""}, + {GHOST_kStandardCursorUpArrow, "sb_up_arrow"}, + {GHOST_kStandardCursorDownArrow, "sb_down_arrow"}, + {GHOST_kStandardCursorVerticalSplit, ""}, + {GHOST_kStandardCursorHorizontalSplit, ""}, + {GHOST_kStandardCursorEraser, ""}, + {GHOST_kStandardCursorKnife, ""}, + {GHOST_kStandardCursorEyedropper, ""}, + {GHOST_kStandardCursorZoomIn, ""}, + {GHOST_kStandardCursorZoomOut, ""}, + {GHOST_kStandardCursorMove, "move"}, + {GHOST_kStandardCursorNSEWScroll, ""}, + {GHOST_kStandardCursorNSScroll, ""}, + {GHOST_kStandardCursorEWScroll, ""}, + {GHOST_kStandardCursorStop, ""}, + {GHOST_kStandardCursorUpDown, "sb_v_double_arrow"}, + {GHOST_kStandardCursorLeftRight, "sb_h_double_arrow"}, + {GHOST_kStandardCursorTopSide, "top_side"}, + {GHOST_kStandardCursorBottomSide, "bottom_side"}, + {GHOST_kStandardCursorLeftSide, "left_side"}, + {GHOST_kStandardCursorRightSide, "right_side"}, + {GHOST_kStandardCursorTopLeftCorner, "top_left_corner"}, + {GHOST_kStandardCursorTopRightCorner, "top_right_corner"}, + {GHOST_kStandardCursorBottomRightCorner, "bottom_right_corner"}, + {GHOST_kStandardCursorBottomLeftCorner, "bottom_left_corner"}, + {GHOST_kStandardCursorCopy, "copy"}, +}; + +static constexpr const char *mime_text_plain = "text/plain"; +static constexpr const char *mime_text_utf8 = "text/plain;charset=utf-8"; +static constexpr const char *mime_text_uri = "text/uri-list"; + +static const std::unordered_map<std::string, GHOST_TDragnDropTypes> mime_dnd = { + {mime_text_plain, GHOST_kDragnDropTypeString}, + {mime_text_utf8, GHOST_kDragnDropTypeString}, + {mime_text_uri, GHOST_kDragnDropTypeFilenames}, +}; + +static const std::vector<std::string> mime_preference_order = { + mime_text_uri, + mime_text_utf8, + mime_text_plain, +}; + +static const std::vector<std::string> mime_send = { + "UTF8_STRING", + "COMPOUND_TEXT", + "TEXT", + "STRING", + "text/plain;charset=utf-8", + "text/plain", +}; + +/* -------------------------------------------------------------------- */ +/** \name Interface Callbacks + * + * These callbacks are registered for Wayland interfaces and called when + * an event is received from the compositor. + * \{ */ + +static void relative_pointer_relative_motion( + void *data, + struct zwp_relative_pointer_v1 * /*zwp_relative_pointer_v1*/, + uint32_t /*utime_hi*/, + uint32_t /*utime_lo*/, + wl_fixed_t dx, + wl_fixed_t dy, + wl_fixed_t /*dx_unaccel*/, + wl_fixed_t /*dy_unaccel*/) +{ + input_t *input = static_cast<input_t *>(data); + + input->x += wl_fixed_to_int(dx); + input->y += wl_fixed_to_int(dy); + + input->system->pushEvent( + new GHOST_EventCursor(input->system->getMilliSeconds(), + GHOST_kEventCursorMove, + input->system->getWindowManager()->getActiveWindow(), + input->x, + input->y, + GHOST_TABLET_DATA_NONE)); +} + +static const zwp_relative_pointer_v1_listener relative_pointer_listener = { + relative_pointer_relative_motion}; + +static void dnd_events(const input_t *const input, const GHOST_TEventType event) +{ + const GHOST_TUns64 time = input->system->getMilliSeconds(); + GHOST_IWindow *const window = input->system->getWindowManager()->getActiveWindow(); + for (const std::string &type : mime_preference_order) { + input->system->pushEvent(new GHOST_EventDragnDrop(time, + event, + mime_dnd.at(type), + window, + input->data_offer_dnd->dnd.x, + input->data_offer_dnd->dnd.y, + nullptr)); + } +} + +static std::string read_pipe(data_offer_t *data_offer, const std::string mime_receive) +{ + int pipefd[2]; + pipe(pipefd); + wl_data_offer_receive(data_offer->id, mime_receive.c_str(), pipefd[1]); + close(pipefd[1]); + + std::string data; + ssize_t len; + char buffer[4096]; + while ((len = read(pipefd[0], buffer, sizeof(buffer))) > 0) { + data.insert(data.end(), buffer, buffer + len); + } + close(pipefd[0]); + data_offer->in_use.store(false); + + return data; +} + +/** + * A target accepts an offered mime type. + * + * Sent when a target accepts pointer_focus or motion events. If + * a target does not accept any of the offered types, type is NULL. + */ +static void data_source_target(void * /*data*/, + struct wl_data_source * /*wl_data_source*/, + const char * /*mime_type*/) +{ + /* pass */ +} + +static void data_source_send(void *data, + struct wl_data_source * /*wl_data_source*/, + const char * /*mime_type*/, + int32_t fd) +{ + const char *const buffer = static_cast<char *>(data); + write(fd, buffer, strlen(buffer) + 1); + close(fd); +} + +static void data_source_cancelled(void * /*data*/, struct wl_data_source *wl_data_source) +{ + wl_data_source_destroy(wl_data_source); +} + +/** + * The drag-and-drop operation physically finished. + * + * The user performed the drop action. This event does not + * indicate acceptance, #wl_data_source.cancelled may still be + * emitted afterwards if the drop destination does not accept any mime type. + */ +static void data_source_dnd_drop_performed(void * /*data*/, + struct wl_data_source * /*wl_data_source*/) +{ + /* pass */ +} + +/** + * The drag-and-drop operation concluded. + * + * The drop destination finished interoperating with this data + * source, so the client is now free to destroy this data source + * and free all associated data. + */ +static void data_source_dnd_finished(void * /*data*/, struct wl_data_source * /*wl_data_source*/) +{ + /* pass */ +} + +/** + * Notify the selected action. + * + * This event indicates the action selected by the compositor + * after matching the source/destination side actions. Only one + * action (or none) will be offered here. + */ +static void data_source_action(void * /*data*/, + struct wl_data_source * /*wl_data_source*/, + uint32_t /*dnd_action*/) +{ + /* pass */ +} + +static const struct wl_data_source_listener data_source_listener = { + data_source_target, + data_source_send, + data_source_cancelled, + data_source_dnd_drop_performed, + data_source_dnd_finished, + data_source_action, +}; + +static void data_offer_offer(void *data, + struct wl_data_offer * /*wl_data_offer*/, + const char *mime_type) +{ + static_cast<data_offer_t *>(data)->types.insert(mime_type); +} + +static void data_offer_source_actions(void *data, + struct wl_data_offer * /*wl_data_offer*/, + uint32_t source_actions) +{ + static_cast<data_offer_t *>(data)->source_actions = source_actions; +} + +static void data_offer_action(void *data, + struct wl_data_offer * /*wl_data_offer*/, + uint32_t dnd_action) +{ + static_cast<data_offer_t *>(data)->dnd_action = dnd_action; +} + +static const struct wl_data_offer_listener data_offer_listener = { + data_offer_offer, + data_offer_source_actions, + data_offer_action, +}; + +static void data_device_data_offer(void * /*data*/, + struct wl_data_device * /*wl_data_device*/, + struct wl_data_offer *id) +{ + data_offer_t *data_offer = new data_offer_t; + data_offer->id = id; + wl_data_offer_add_listener(id, &data_offer_listener, data_offer); +} + +static void data_device_enter(void *data, + struct wl_data_device * /*wl_data_device*/, + uint32_t serial, + struct wl_surface * /*surface*/, + wl_fixed_t x, + wl_fixed_t y, + struct wl_data_offer *id) +{ + input_t *input = static_cast<input_t *>(data); + input->data_offer_dnd = static_cast<data_offer_t *>(wl_data_offer_get_user_data(id)); + data_offer_t *data_offer = input->data_offer_dnd; + + data_offer->in_use.store(true); + data_offer->dnd.x = wl_fixed_to_int(x); + data_offer->dnd.y = wl_fixed_to_int(y); + + wl_data_offer_set_actions(id, + WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY | + WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE, + WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY); + + for (const std::string &type : mime_preference_order) { + wl_data_offer_accept(id, serial, type.c_str()); + } + + dnd_events(input, GHOST_kEventDraggingEntered); +} + +static void data_device_leave(void *data, struct wl_data_device * /*wl_data_device*/) +{ + input_t *input = static_cast<input_t *>(data); + + dnd_events(input, GHOST_kEventDraggingExited); + + if (input->data_offer_dnd && !input->data_offer_dnd->in_use.load()) { + wl_data_offer_destroy(input->data_offer_dnd->id); + delete input->data_offer_dnd; + input->data_offer_dnd = nullptr; + } +} + +static void data_device_motion(void *data, + struct wl_data_device * /*wl_data_device*/, + uint32_t /*time*/, + wl_fixed_t x, + wl_fixed_t y) +{ + input_t *input = static_cast<input_t *>(data); + input->data_offer_dnd->dnd.x = wl_fixed_to_int(x); + input->data_offer_dnd->dnd.y = wl_fixed_to_int(y); + dnd_events(input, GHOST_kEventDraggingUpdated); +} + +static void data_device_drop(void *data, struct wl_data_device * /*wl_data_device*/) +{ + input_t *input = static_cast<input_t *>(data); + data_offer_t *data_offer = input->data_offer_dnd; + + const std::string mime_receive = *std::find_first_of(mime_preference_order.begin(), + mime_preference_order.end(), + data_offer->types.begin(), + data_offer->types.end()); + + auto read_uris = [](GHOST_SystemWayland *const system, + data_offer_t *data_offer, + const std::string mime_receive) { + const int x = data_offer->dnd.x; + const int y = data_offer->dnd.y; + + const std::string data = read_pipe(data_offer, mime_receive); + + wl_data_offer_finish(data_offer->id); + wl_data_offer_destroy(data_offer->id); + + delete data_offer; + data_offer = nullptr; + + if (mime_receive == mime_text_uri) { + static constexpr const char *file_proto = "file://"; + static constexpr const char *crlf = "\r\n"; + + std::vector<std::string> uris; + + size_t pos = 0; + while (true) { + pos = data.find(file_proto, pos); + const size_t start = pos + sizeof(file_proto) - 1; + pos = data.find(crlf, pos); + const size_t end = pos; + + if (pos == std::string::npos) { + break; + } + uris.push_back(data.substr(start, end - start)); + } + + GHOST_TStringArray *flist = static_cast<GHOST_TStringArray *>( + malloc(sizeof(GHOST_TStringArray))); + flist->count = int(uris.size()); + flist->strings = static_cast<GHOST_TUns8 **>(malloc(uris.size() * sizeof(GHOST_TUns8 *))); + for (size_t i = 0; i < uris.size(); i++) { + flist->strings[i] = static_cast<GHOST_TUns8 *>( + malloc((uris[i].size() + 1) * sizeof(GHOST_TUns8))); + memcpy(flist->strings[i], uris[i].data(), uris[i].size() + 1); + } + system->pushEvent(new GHOST_EventDragnDrop(system->getMilliSeconds(), + GHOST_kEventDraggingDropDone, + GHOST_kDragnDropTypeFilenames, + system->getWindowManager()->getActiveWindow(), + x, + y, + flist)); + } + else if (mime_receive == mime_text_plain || mime_receive == mime_text_utf8) { + /* TODO: enable use of internal functions 'txt_insert_buf' and + * 'text_update_edited' to behave like dropped text was pasted. */ + } + wl_display_roundtrip(system->display()); + }; + + std::thread read_thread(read_uris, input->system, data_offer, mime_receive); + read_thread.detach(); +} + +static void data_device_selection(void *data, + struct wl_data_device * /*wl_data_device*/, + struct wl_data_offer *id) +{ + input_t *input = static_cast<input_t *>(data); + data_offer_t *data_offer = input->data_offer_copy_paste; + + /* Delete old data offer. */ + if (data_offer != nullptr) { + wl_data_offer_destroy(data_offer->id); + delete data_offer; + data_offer = nullptr; + } + + if (id == nullptr) { + return; + } + + /* Get new data offer. */ + data_offer = static_cast<data_offer_t *>(wl_data_offer_get_user_data(id)); + input->data_offer_copy_paste = data_offer; + + std::string mime_receive; + for (const std::string &type : {mime_text_utf8, mime_text_plain}) { + if (data_offer->types.count(type)) { + mime_receive = type; + break; + } + } + + auto read_selection = [](GHOST_SystemWayland *const system, + data_offer_t *data_offer, + const std::string mime_receive) { + const std::string data = read_pipe(data_offer, mime_receive); + system->setSelection(data); + }; + + std::thread read_thread(read_selection, input->system, data_offer, mime_receive); + read_thread.detach(); +} + +static const struct wl_data_device_listener data_device_listener = { + data_device_data_offer, + data_device_enter, + data_device_leave, + data_device_motion, + data_device_drop, + data_device_selection, +}; + +static void buffer_release(void * /*data*/, struct wl_buffer *wl_buffer) +{ + wl_buffer_destroy(wl_buffer); +} + +const struct wl_buffer_listener buffer_listener = { + buffer_release, +}; + +static void pointer_enter(void *data, + struct wl_pointer * /*wl_pointer*/, + uint32_t serial, + struct wl_surface *surface, + wl_fixed_t surface_x, + wl_fixed_t surface_y) +{ + if (!surface) { + return; + } + input_t *input = static_cast<input_t *>(data); + input->pointer_serial = serial; + input->x = wl_fixed_to_int(surface_x); + input->y = wl_fixed_to_int(surface_y); + + static_cast<GHOST_WindowWayland *>(wl_surface_get_user_data(surface))->activate(); +} + +static void pointer_leave(void * /*data*/, + struct wl_pointer * /*wl_pointer*/, + uint32_t /*serial*/, + struct wl_surface *surface) +{ + if (surface != nullptr) { + static_cast<GHOST_WindowWayland *>(wl_surface_get_user_data(surface))->deactivate(); + } +} + +static void pointer_motion(void *data, + struct wl_pointer * /*wl_pointer*/, + uint32_t /*time*/, + wl_fixed_t surface_x, + wl_fixed_t surface_y) +{ + input_t *input = static_cast<input_t *>(data); + + input->x = wl_fixed_to_int(surface_x); + input->y = wl_fixed_to_int(surface_y); + + input->system->pushEvent( + new GHOST_EventCursor(input->system->getMilliSeconds(), + GHOST_kEventCursorMove, + input->system->getWindowManager()->getActiveWindow(), + wl_fixed_to_int(surface_x), + wl_fixed_to_int(surface_y), + GHOST_TABLET_DATA_NONE)); +} + +static void pointer_button(void *data, + struct wl_pointer * /*wl_pointer*/, + uint32_t serial, + uint32_t /*time*/, + uint32_t button, + uint32_t state) +{ + GHOST_TEventType etype = GHOST_kEventUnknown; + switch (state) { + case WL_POINTER_BUTTON_STATE_RELEASED: + etype = GHOST_kEventButtonUp; + break; + case WL_POINTER_BUTTON_STATE_PRESSED: + etype = GHOST_kEventButtonDown; + break; + } + + GHOST_TButtonMask ebutton = GHOST_kButtonMaskLeft; + switch (button) { + case BTN_LEFT: + ebutton = GHOST_kButtonMaskLeft; + break; + case BTN_MIDDLE: + ebutton = GHOST_kButtonMaskMiddle; + break; + case BTN_RIGHT: + ebutton = GHOST_kButtonMaskRight; + break; + } + + input_t *input = static_cast<input_t *>(data); + input->data_source->source_serial = serial; + input->buttons.set(ebutton, state == WL_POINTER_BUTTON_STATE_PRESSED); + input->system->pushEvent( + new GHOST_EventButton(input->system->getMilliSeconds(), + etype, + input->system->getWindowManager()->getActiveWindow(), + ebutton, + GHOST_TABLET_DATA_NONE)); +} + +static void pointer_axis(void *data, + struct wl_pointer * /*wl_pointer*/, + uint32_t /*time*/, + uint32_t axis, + wl_fixed_t value) +{ + if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL) { + return; + } + input_t *input = static_cast<input_t *>(data); + input->system->pushEvent( + new GHOST_EventWheel(input->system->getMilliSeconds(), + input->system->getWindowManager()->getActiveWindow(), + std::signbit(value) ? +1 : -1)); +} + +static const struct wl_pointer_listener pointer_listener = { + pointer_enter, + pointer_leave, + pointer_motion, + pointer_button, + pointer_axis, +}; + +static void keyboard_keymap( + void *data, struct wl_keyboard * /*wl_keyboard*/, uint32_t format, int32_t fd, uint32_t size) +{ + input_t *input = static_cast<input_t *>(data); + + if ((!data) || (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1)) { + close(fd); + return; + } + + char *map_str = static_cast<char *>(mmap(nullptr, size, PROT_READ, MAP_PRIVATE, fd, 0)); + if (map_str == MAP_FAILED) { + close(fd); + throw std::runtime_error("keymap mmap failed: " + std::string(std::strerror(errno))); + } + + struct xkb_keymap *keymap = xkb_keymap_new_from_string( + input->xkb_context, map_str, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS); + munmap(map_str, size); + close(fd); + + if (!keymap) { + return; + } + + input->xkb_state = xkb_state_new(keymap); + + xkb_keymap_unref(keymap); +} + +/** + * Enter event. + * + * Notification that this seat's keyboard focus is on a certain + * surface. + */ +static void keyboard_enter(void * /*data*/, + struct wl_keyboard * /*wl_keyboard*/, + uint32_t /*serial*/, + struct wl_surface * /*surface*/, + struct wl_array * /*keys*/) +{ + /* pass */ +} + +/** + * Leave event. + * + * Notification that this seat's keyboard focus is no longer on a + * certain surface. + */ +static void keyboard_leave(void * /*data*/, + struct wl_keyboard * /*wl_keyboard*/, + uint32_t /*serial*/, + struct wl_surface * /*surface*/) +{ + /* pass */ +} + +static void keyboard_key(void *data, + struct wl_keyboard * /*wl_keyboard*/, + uint32_t serial, + uint32_t /*time*/, + uint32_t key, + uint32_t state) +{ + input_t *input = static_cast<input_t *>(data); + + GHOST_TEventType etype = GHOST_kEventUnknown; + switch (state) { + case WL_KEYBOARD_KEY_STATE_RELEASED: + etype = GHOST_kEventKeyUp; + break; + case WL_KEYBOARD_KEY_STATE_PRESSED: + etype = GHOST_kEventKeyDown; + break; + } + + const xkb_keysym_t sym = xkb_state_key_get_one_sym(input->xkb_state, key + 8); + if (sym == XKB_KEY_NoSymbol) { + return; + } + const GHOST_TKey gkey = xkb_map_gkey(sym); + + GHOST_TEventKeyData key_data; + + if (etype == GHOST_kEventKeyDown) { + xkb_state_key_get_utf8( + input->xkb_state, key + 8, key_data.utf8_buf, sizeof(GHOST_TEventKeyData::utf8_buf)); + } + else { + key_data.utf8_buf[0] = '\0'; + } + + input->data_source->source_serial = serial; + input->system->pushEvent(new GHOST_EventKey(input->system->getMilliSeconds(), + etype, + input->system->getWindowManager()->getActiveWindow(), + gkey, + '\0', + key_data.utf8_buf, + false)); +} + +static void keyboard_modifiers(void *data, + struct wl_keyboard * /*wl_keyboard*/, + uint32_t /*serial*/, + uint32_t mods_depressed, + uint32_t mods_latched, + uint32_t mods_locked, + uint32_t group) +{ + xkb_state_update_mask(static_cast<input_t *>(data)->xkb_state, + mods_depressed, + mods_latched, + mods_locked, + 0, + 0, + group); +} + +static const struct wl_keyboard_listener keyboard_listener = { + keyboard_keymap, + keyboard_enter, + keyboard_leave, + keyboard_key, + keyboard_modifiers, +}; + +static void seat_capabilities(void *data, struct wl_seat *wl_seat, uint32_t capabilities) +{ + input_t *input = static_cast<input_t *>(data); + input->pointer = nullptr; + input->keyboard = nullptr; + + if (capabilities & WL_SEAT_CAPABILITY_POINTER) { + input->pointer = wl_seat_get_pointer(wl_seat); + input->cursor.surface = wl_compositor_create_surface(input->system->compositor()); + input->cursor.visible = true; + input->cursor.buffer = nullptr; + input->cursor.file_buffer = new buffer_t; + wl_pointer_add_listener(input->pointer, &pointer_listener, data); + } + + if (capabilities & WL_SEAT_CAPABILITY_KEYBOARD) { + input->keyboard = wl_seat_get_keyboard(wl_seat); + wl_keyboard_add_listener(input->keyboard, &keyboard_listener, data); + } +} + +static void seat_name(void *data, struct wl_seat * /*wl_seat*/, const char *name) +{ + static_cast<input_t *>(data)->name = std::string(name); +} + +static const struct wl_seat_listener seat_listener = { + seat_capabilities, + seat_name, +}; + +static void output_geometry(void *data, + struct wl_output * /*wl_output*/, + int32_t /*x*/, + int32_t /*y*/, + int32_t /*physical_width*/, + int32_t /*physical_height*/, + int32_t /*subpixel*/, + const char *make, + const char *model, + int32_t transform) +{ + output_t *output = static_cast<output_t *>(data); + output->transform = transform; + output->make = std::string(make); + output->model = std::string(model); +} + +static void output_mode(void *data, + struct wl_output * /*wl_output*/, + uint32_t /*flags*/, + int32_t width, + int32_t height, + int32_t /*refresh*/) +{ + output_t *output = static_cast<output_t *>(data); + output->width = width; + output->height = height; +} + +/** + * Sent all information about output. + * + * This event is sent after all other properties have been sent + * after binding to the output object and after any other property + * changes done after that. This allows changes to the output + * properties to be seen as atomic, even if they happen via multiple events. + */ +static void output_done(void * /*data*/, struct wl_output * /*wl_output*/) +{ +} + +static void output_scale(void *data, struct wl_output * /*wl_output*/, int32_t factor) +{ + static_cast<output_t *>(data)->scale = factor; +} + +static const struct wl_output_listener output_listener = { + output_geometry, + output_mode, + output_done, + output_scale, +}; + +static void shell_ping(void * /*data*/, struct xdg_wm_base *xdg_wm_base, uint32_t serial) +{ + xdg_wm_base_pong(xdg_wm_base, serial); +} + +static const struct xdg_wm_base_listener shell_listener = { + shell_ping, +}; + +static void global_add(void *data, + struct wl_registry *wl_registry, + uint32_t name, + const char *interface, + uint32_t /*version*/) +{ + struct display_t *display = static_cast<struct display_t *>(data); + if (!strcmp(interface, wl_compositor_interface.name)) { + display->compositor = static_cast<wl_compositor *>( + wl_registry_bind(wl_registry, name, &wl_compositor_interface, 1)); + } + else if (!strcmp(interface, xdg_wm_base_interface.name)) { + display->xdg_shell = static_cast<xdg_wm_base *>( + wl_registry_bind(wl_registry, name, &xdg_wm_base_interface, 1)); + xdg_wm_base_add_listener(display->xdg_shell, &shell_listener, nullptr); + } + else if (!strcmp(interface, wl_output_interface.name)) { + output_t *output = new output_t; + output->scale = 1; + output->output = static_cast<wl_output *>( + wl_registry_bind(wl_registry, name, &wl_output_interface, 2)); + display->outputs.push_back(output); + wl_output_add_listener(output->output, &output_listener, output); + } + else if (!strcmp(interface, wl_seat_interface.name)) { + input_t *input = new input_t; + input->system = display->system; + input->xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + input->xkb_state = nullptr; + input->data_offer_dnd = nullptr; + input->data_offer_copy_paste = nullptr; + input->data_source = new data_source_t; + input->data_source->data_source = nullptr; + input->data_source->buffer_out = nullptr; + input->relative_pointer = nullptr; + input->locked_pointer = nullptr; + input->seat = static_cast<wl_seat *>( + wl_registry_bind(wl_registry, name, &wl_seat_interface, 2)); + display->inputs.push_back(input); + wl_seat_add_listener(input->seat, &seat_listener, input); + } + else if (!strcmp(interface, wl_shm_interface.name)) { + display->shm = static_cast<wl_shm *>( + wl_registry_bind(wl_registry, name, &wl_shm_interface, 1)); + } + else if (!strcmp(interface, wl_data_device_manager_interface.name)) { + display->data_device_manager = static_cast<wl_data_device_manager *>( + wl_registry_bind(wl_registry, name, &wl_data_device_manager_interface, 1)); + } + else if (!strcmp(interface, zwp_relative_pointer_manager_v1_interface.name)) { + display->relative_pointer_manager = static_cast<zwp_relative_pointer_manager_v1 *>( + wl_registry_bind(wl_registry, name, &zwp_relative_pointer_manager_v1_interface, 1)); + } + else if (!strcmp(interface, zwp_pointer_constraints_v1_interface.name)) { + display->pointer_constraints = static_cast<zwp_pointer_constraints_v1 *>( + wl_registry_bind(wl_registry, name, &zwp_pointer_constraints_v1_interface, 1)); + } +} + +/** + * Announce removal of global object. + * + * Notify the client of removed global objects. + * + * This event notifies the client that the global identified by + * name is no longer available. If the client bound to the global + * using the bind request, the client should now destroy that object. + */ +static void global_remove(void * /*data*/, struct wl_registry * /*wl_registry*/, uint32_t /*name*/) +{ +} + +static const struct wl_registry_listener registry_listener = { + global_add, + global_remove, +}; + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Ghost Implementation + * + * Wayland specific implementation of the GHOST_System interface. + * \{ */ + +GHOST_SystemWayland::GHOST_SystemWayland() : GHOST_System(), d(new display_t) +{ + d->system = this; + /* Connect to the Wayland server. */ + d->display = wl_display_connect(nullptr); + if (!d->display) { + display_destroy(d); + throw std::runtime_error("Wayland: unable to connect to display!"); + } + + /* Register interfaces. */ + struct wl_registry *registry = wl_display_get_registry(d->display); + wl_registry_add_listener(registry, ®istry_listener, d); + /* Call callback for registry listener. */ + wl_display_roundtrip(d->display); + /* Call callbacks for registered listeners. */ + wl_display_roundtrip(d->display); + wl_registry_destroy(registry); + + if (!d->xdg_shell) { + display_destroy(d); + throw std::runtime_error("Wayland: unable to access xdg_shell!"); + } + + /* Register data device per seat for IPC between Wayland clients. */ + if (d->data_device_manager) { + for (input_t *input : d->inputs) { + input->data_device = wl_data_device_manager_get_data_device(d->data_device_manager, + input->seat); + wl_data_device_add_listener(input->data_device, &data_device_listener, input); + } + } + + const char *theme = std::getenv("XCURSOR_THEME"); + const char *size = std::getenv("XCURSOR_SIZE"); + const int sizei = size ? std::stoi(size) : default_cursor_size; + + d->cursor_theme = wl_cursor_theme_load(theme, sizei, d->shm); + if (!d->cursor_theme) { + display_destroy(d); + throw std::runtime_error("Wayland: unable to access cursor themes!"); + } +} + +GHOST_SystemWayland::~GHOST_SystemWayland() +{ + display_destroy(d); +} + +bool GHOST_SystemWayland::processEvents(bool /*waitForEvent*/) +{ + wl_display_dispatch(d->display); + return true; +} + +int GHOST_SystemWayland::toggleConsole(int /*action*/) +{ + return 0; +} + +GHOST_TSuccess GHOST_SystemWayland::getModifierKeys(GHOST_ModifierKeys &keys) const +{ + if (!d->inputs.empty()) { + static const xkb_state_component mods_all = xkb_state_component( + XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_LOCKED | + XKB_STATE_MODS_EFFECTIVE); + + keys.set(GHOST_kModifierKeyLeftShift, + xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, XKB_MOD_NAME_SHIFT, mods_all) == + 1); + keys.set(GHOST_kModifierKeyRightShift, + xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, XKB_MOD_NAME_SHIFT, mods_all) == + 1); + keys.set(GHOST_kModifierKeyLeftAlt, + xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, "LAlt", mods_all) == 1); + keys.set(GHOST_kModifierKeyRightAlt, + xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, "RAlt", mods_all) == 1); + keys.set(GHOST_kModifierKeyLeftControl, + xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, "LControl", mods_all) == 1); + keys.set(GHOST_kModifierKeyRightControl, + xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, "RControl", mods_all) == 1); + keys.set(GHOST_kModifierKeyOS, + xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, "Super", mods_all) == 1); + keys.set(GHOST_kModifierKeyNumMasks, + xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, "NumLock", mods_all) == 1); + + return GHOST_kSuccess; + } + return GHOST_kFailure; +} + +GHOST_TSuccess GHOST_SystemWayland::getButtons(GHOST_Buttons &buttons) const +{ + if (!d->inputs.empty()) { + buttons = d->inputs[0]->buttons; + return GHOST_kSuccess; + } + return GHOST_kFailure; +} + +GHOST_TUns8 *GHOST_SystemWayland::getClipboard(bool /*selection*/) const +{ + GHOST_TUns8 *clipboard = static_cast<GHOST_TUns8 *>(malloc((selection.size() + 1))); + memcpy(clipboard, selection.data(), selection.size() + 1); + return clipboard; +} + +void GHOST_SystemWayland::putClipboard(GHOST_TInt8 *buffer, bool /*selection*/) const +{ + if (!d->data_device_manager || d->inputs.empty()) { + return; + } + + data_source_t *data_source = d->inputs[0]->data_source; + + /* Copy buffer. */ + data_source->buffer_out = static_cast<char *>(malloc(strlen(buffer) + 1)); + std::strcpy(data_source->buffer_out, buffer); + + data_source->data_source = wl_data_device_manager_create_data_source(d->data_device_manager); + + wl_data_source_add_listener( + data_source->data_source, &data_source_listener, data_source->buffer_out); + + for (const std::string &type : mime_send) { + wl_data_source_offer(data_source->data_source, type.c_str()); + } + + if (!d->inputs.empty() && d->inputs[0]->data_device) { + wl_data_device_set_selection( + d->inputs[0]->data_device, data_source->data_source, data_source->source_serial); + } +} + +GHOST_TUns8 GHOST_SystemWayland::getNumDisplays() const +{ + return d ? GHOST_TUns8(d->outputs.size()) : 0; +} + +GHOST_TSuccess GHOST_SystemWayland::getCursorPosition(GHOST_TInt32 &x, GHOST_TInt32 &y) const +{ + if (getWindowManager()->getActiveWindow() != nullptr && !d->inputs.empty()) { + x = d->inputs[0]->x; + y = d->inputs[0]->y; + return GHOST_kSuccess; + } + else { + return GHOST_kFailure; + } +} + +GHOST_TSuccess GHOST_SystemWayland::setCursorPosition(GHOST_TInt32 /*x*/, GHOST_TInt32 /*y*/) +{ + return GHOST_kFailure; +} + +void GHOST_SystemWayland::getMainDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const +{ + if (getNumDisplays() > 0) { + /* We assume first output as main. */ + width = uint32_t(d->outputs[0]->width); + height = uint32_t(d->outputs[0]->height); + } +} + +void GHOST_SystemWayland::getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const +{ + getMainDisplayDimensions(width, height); +} + +GHOST_IContext *GHOST_SystemWayland::createOffscreenContext() +{ + /* Create new off-screen window. */ + wl_surface *os_surface = wl_compositor_create_surface(compositor()); + wl_egl_window *os_egl_window = wl_egl_window_create(os_surface, int(1), int(1)); + + d->os_surfaces.push_back(os_surface); + d->os_egl_windows.push_back(os_egl_window); + + GHOST_Context *context = new GHOST_ContextEGL(false, + EGLNativeWindowType(os_egl_window), + EGLNativeDisplayType(d->display), + EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT, + 3, + 3, + GHOST_OPENGL_EGL_CONTEXT_FLAGS, + GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY, + EGL_OPENGL_API); + + if (context->initializeDrawingContext()) { + return context; + } + else { + delete context; + } + + GHOST_PRINT("Cannot create off-screen EGL context" << std::endl); + + return nullptr; +} + +GHOST_TSuccess GHOST_SystemWayland::disposeContext(GHOST_IContext *context) +{ + delete context; + return GHOST_kSuccess; +} + +GHOST_IWindow *GHOST_SystemWayland::createWindow(const char *title, + GHOST_TInt32 left, + GHOST_TInt32 top, + GHOST_TUns32 width, + GHOST_TUns32 height, + GHOST_TWindowState state, + GHOST_TDrawingContextType type, + GHOST_GLSettings glSettings, + const bool exclusive, + const bool /*is_dialog*/, + const GHOST_IWindow *parentWindow) +{ + GHOST_WindowWayland *window = new GHOST_WindowWayland( + this, + title, + left, + top, + width, + height, + state, + parentWindow, + type, + ((glSettings.flags & GHOST_glStereoVisual) != 0), + exclusive); + + if (window) { + if (window->getValid()) { + m_windowManager->addWindow(window); + m_windowManager->setActiveWindow(window); + pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window)); + } + else { + delete window; + window = nullptr; + } + } + + return window; +} + +wl_display *GHOST_SystemWayland::display() +{ + return d->display; +} + +wl_compositor *GHOST_SystemWayland::compositor() +{ + return d->compositor; +} + +xdg_wm_base *GHOST_SystemWayland::shell() +{ + return d->xdg_shell; +} + +void GHOST_SystemWayland::setSelection(const std::string &selection) +{ + this->selection = selection; +} + +static void set_cursor_buffer(input_t *input, wl_buffer *buffer) +{ + input->cursor.visible = (buffer != nullptr); + + wl_surface_attach(input->cursor.surface, buffer, 0, 0); + wl_surface_commit(input->cursor.surface); + + if (input->cursor.visible) { + wl_surface_damage(input->cursor.surface, + 0, + 0, + int32_t(input->cursor.image.width), + int32_t(input->cursor.image.height)); + wl_pointer_set_cursor(input->pointer, + input->pointer_serial, + input->cursor.surface, + int32_t(input->cursor.image.hotspot_x), + int32_t(input->cursor.image.hotspot_y)); + } +} + +GHOST_TSuccess GHOST_SystemWayland::setCursorShape(GHOST_TStandardCursor shape) +{ + if (d->inputs.empty()) { + return GHOST_kFailure; + } + const std::string cursor_name = cursors.count(shape) ? cursors.at(shape) : + cursors.at(GHOST_kStandardCursorDefault); + + wl_cursor *cursor = wl_cursor_theme_get_cursor(d->cursor_theme, cursor_name.c_str()); + + if (!cursor) { + GHOST_PRINT("cursor '" << cursor_name << "' does not exist" << std::endl); + return GHOST_kFailure; + } + + struct wl_cursor_image *image = cursor->images[0]; + struct wl_buffer *buffer = wl_cursor_image_get_buffer(image); + if (!buffer) { + return GHOST_kFailure; + } + cursor_t *c = &d->inputs[0]->cursor; + c->buffer = buffer; + c->image = *image; + + set_cursor_buffer(d->inputs[0], buffer); + + return GHOST_kSuccess; +} + +GHOST_TSuccess GHOST_SystemWayland::hasCursorShape(GHOST_TStandardCursor cursorShape) +{ + return GHOST_TSuccess(cursors.count(cursorShape) && !cursors.at(cursorShape).empty()); +} + +GHOST_TSuccess GHOST_SystemWayland::setCustomCursorShape(GHOST_TUns8 *bitmap, + GHOST_TUns8 *mask, + int sizex, + int sizey, + int hotX, + int hotY, + bool /*canInvertColor*/) +{ + if (d->inputs.empty()) { + return GHOST_kFailure; + } + + cursor_t *cursor = &d->inputs[0]->cursor; + + static const int32_t stride = sizex * 4; /* ARGB */ + cursor->file_buffer->size = size_t(stride * sizey); + + const int fd = memfd_create("blender-cursor-custom", MFD_CLOEXEC | MFD_ALLOW_SEALING); + fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK); + posix_fallocate(fd, 0, int32_t(cursor->file_buffer->size)); + + cursor->file_buffer->data = mmap( + nullptr, cursor->file_buffer->size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + + struct wl_shm_pool *pool = wl_shm_create_pool(d->shm, fd, int32_t(cursor->file_buffer->size)); + + wl_buffer *buffer = wl_shm_pool_create_buffer( + pool, 0, sizex, sizey, stride, WL_SHM_FORMAT_ARGB8888); + + wl_shm_pool_destroy(pool); + close(fd); + + wl_buffer_add_listener(buffer, &buffer_listener, nullptr); + + static constexpr uint32_t black = 0xFF000000; + static constexpr uint32_t white = 0xFFFFFFFF; + static constexpr uint32_t transparent = 0x00000000; + + uint8_t datab = 0, maskb = 0; + uint32_t *pixel; + + for (int y = 0; y < sizey; ++y) { + pixel = &static_cast<uint32_t *>(cursor->file_buffer->data)[y * sizex]; + for (int x = 0; x < sizex; ++x) { + if ((x % 8) == 0) { + datab = *bitmap++; + maskb = *mask++; + + /* Reverse bit order. */ + datab = uint8_t((datab * 0x0202020202ULL & 0x010884422010ULL) % 1023); + maskb = uint8_t((maskb * 0x0202020202ULL & 0x010884422010ULL) % 1023); + } + + if (maskb & 0x80) { + *pixel++ = (datab & 0x80) ? white : black; + } + else { + *pixel++ = (datab & 0x80) ? white : transparent; + } + datab <<= 1; + maskb <<= 1; + } + } + + cursor->buffer = buffer; + cursor->image.width = uint32_t(sizex); + cursor->image.height = uint32_t(sizey); + cursor->image.hotspot_x = uint32_t(hotX); + cursor->image.hotspot_y = uint32_t(hotY); + + set_cursor_buffer(d->inputs[0], buffer); + + return GHOST_kSuccess; +} + +GHOST_TSuccess GHOST_SystemWayland::setCursorVisibility(bool visible) +{ + if (d->inputs.empty()) { + return GHOST_kFailure; + } + + cursor_t *cursor = &d->inputs[0]->cursor; + if (visible) { + if (!cursor->visible) { + set_cursor_buffer(d->inputs[0], d->inputs[0]->cursor.buffer); + } + } + else { + if (cursor->visible) { + set_cursor_buffer(d->inputs[0], nullptr); + } + } + + return GHOST_kSuccess; +} + +GHOST_TSuccess GHOST_SystemWayland::setCursorGrab(const GHOST_TGrabCursorMode mode, + wl_surface *surface) +{ + if (d->inputs.empty()) { + return GHOST_kFailure; + } + + input_t *input = d->inputs[0]; + + switch (mode) { + case GHOST_kGrabDisable: + if (input->relative_pointer) { + zwp_relative_pointer_v1_destroy(input->relative_pointer); + input->relative_pointer = nullptr; + } + if (input->locked_pointer) { + zwp_locked_pointer_v1_destroy(input->locked_pointer); + input->locked_pointer = nullptr; + } + break; + + case GHOST_kGrabNormal: + case GHOST_kGrabWrap: + input->relative_pointer = zwp_relative_pointer_manager_v1_get_relative_pointer( + d->relative_pointer_manager, input->pointer); + zwp_relative_pointer_v1_add_listener( + input->relative_pointer, &relative_pointer_listener, input); + input->locked_pointer = zwp_pointer_constraints_v1_lock_pointer( + d->pointer_constraints, + surface, + input->pointer, + nullptr, + ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT); + break; + + case GHOST_kGrabHide: + setCursorVisibility(false); + break; + } + + return GHOST_kSuccess; +} + +/** \} */ diff --git a/intern/ghost/intern/GHOST_SystemWayland.h b/intern/ghost/intern/GHOST_SystemWayland.h new file mode 100644 index 00000000000..89cd3406b69 --- /dev/null +++ b/intern/ghost/intern/GHOST_SystemWayland.h @@ -0,0 +1,111 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup GHOST + * Declaration of GHOST_SystemWayland class. + */ + +#ifndef __GHOST_SYSTEMWAYLAND_H__ +#define __GHOST_SYSTEMWAYLAND_H__ + +#include "../GHOST_Types.h" +#include "GHOST_System.h" +#include "GHOST_WindowWayland.h" + +#include <wayland-client.h> +#include <xdg-shell-client-protocol.h> + +#include <string> + +class GHOST_WindowWayland; + +struct display_t; + +class GHOST_SystemWayland : public GHOST_System { + public: + GHOST_SystemWayland(); + + ~GHOST_SystemWayland() override; + + bool processEvents(bool waitForEvent) override; + + int toggleConsole(int action) override; + + GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys &keys) const override; + + GHOST_TSuccess getButtons(GHOST_Buttons &buttons) const override; + + GHOST_TUns8 *getClipboard(bool selection) const override; + + void putClipboard(GHOST_TInt8 *buffer, bool selection) const override; + + GHOST_TUns8 getNumDisplays() const override; + + GHOST_TSuccess getCursorPosition(GHOST_TInt32 &x, GHOST_TInt32 &y) const override; + + GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) override; + + void getMainDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const override; + + void getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const override; + + GHOST_IContext *createOffscreenContext() override; + + GHOST_TSuccess disposeContext(GHOST_IContext *context) override; + + GHOST_IWindow *createWindow(const char *title, + GHOST_TInt32 left, + GHOST_TInt32 top, + GHOST_TUns32 width, + GHOST_TUns32 height, + GHOST_TWindowState state, + GHOST_TDrawingContextType type, + GHOST_GLSettings glSettings, + const bool exclusive, + const bool is_dialog, + const GHOST_IWindow *parentWindow) override; + + wl_display *display(); + + wl_compositor *compositor(); + + xdg_wm_base *shell(); + + void setSelection(const std::string &selection); + + GHOST_TSuccess setCursorShape(GHOST_TStandardCursor shape); + + GHOST_TSuccess hasCursorShape(GHOST_TStandardCursor cursorShape); + + GHOST_TSuccess setCustomCursorShape(GHOST_TUns8 *bitmap, + GHOST_TUns8 *mask, + int sizex, + int sizey, + int hotX, + int hotY, + bool canInvertColor); + + GHOST_TSuccess setCursorVisibility(bool visible); + + GHOST_TSuccess setCursorGrab(const GHOST_TGrabCursorMode mode, wl_surface *surface); + + private: + struct display_t *d; + std::string selection; +}; + +#endif /* __GHOST_SYSTEMWAYLAND_H__ */ diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index fdd022e44ac..849aa5a96f5 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -282,7 +282,7 @@ void GHOST_SystemWin32::getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns3 height = ::GetSystemMetrics(SM_CYVIRTUALSCREEN); } -GHOST_IWindow *GHOST_SystemWin32::createWindow(const STR_String &title, +GHOST_IWindow *GHOST_SystemWin32::createWindow(const char *title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h index c6d810d2a38..b23f907608c 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.h +++ b/intern/ghost/intern/GHOST_SystemWin32.h @@ -126,7 +126,7 @@ class GHOST_SystemWin32 : public GHOST_System { * \param parentWindow Parent window * \return The new window (or 0 if creation failed). */ - GHOST_IWindow *createWindow(const STR_String &title, + GHOST_IWindow *createWindow(const char *title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index 825b93de36f..91c63a3fb76 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -338,7 +338,7 @@ void GHOST_SystemX11::getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 * \param parentWindow Parent window * \return The new window (or 0 if creation failed). */ -GHOST_IWindow *GHOST_SystemX11::createWindow(const STR_String &title, +GHOST_IWindow *GHOST_SystemX11::createWindow(const char *title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, @@ -1881,7 +1881,7 @@ static GHOST_TKey ghost_key_from_keysym(const KeySym key) # endif #endif default: -#ifdef GHOST_DEBUG +#ifdef WITH_GHOST_DEBUG printf("%s: unknown key: %lu / 0x%lx\n", __func__, key, key); #endif type = GHOST_kKeyUnknown; @@ -1905,7 +1905,7 @@ static GHOST_TKey ghost_key_from_keycode(const XkbDescPtr xkb_descr, const KeyCo switch (id) { case MAKE_ID('T', 'L', 'D', 'E'): return GHOST_kKeyAccentGrave; -#ifdef GHOST_DEBUG +#ifdef WITH_GHOST_DEBUG default: printf("%s unhandled keycode: %.*s\n", __func__, XkbKeyNameLength, id_str); break; @@ -2456,7 +2456,7 @@ GHOST_TSuccess GHOST_SystemX11::showMessageBox(const char *title, string cmd = "xdg-open \"" + string(link) + "\""; if (system(cmd.c_str()) != 0) { GHOST_PRINTF("GHOST_SystemX11::showMessageBox: Unable to run system command [%s]", - cmd); + cmd.c_str()); } } break; diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h index d0e0506e77b..bb01ef7e0cc 100644 --- a/intern/ghost/intern/GHOST_SystemX11.h +++ b/intern/ghost/intern/GHOST_SystemX11.h @@ -137,7 +137,7 @@ class GHOST_SystemX11 : public GHOST_System { * \param parentWindow Parent (embedder) window * \return The new window (or 0 if creation failed). */ - GHOST_IWindow *createWindow(const STR_String &title, + GHOST_IWindow *createWindow(const char *title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, diff --git a/intern/ghost/intern/GHOST_Window.h b/intern/ghost/intern/GHOST_Window.h index 553a7d89df4..472149148e6 100644 --- a/intern/ghost/intern/GHOST_Window.h +++ b/intern/ghost/intern/GHOST_Window.h @@ -27,7 +27,6 @@ #include "GHOST_IWindow.h" -class STR_String; class GHOST_Context; /** @@ -61,8 +60,8 @@ class GHOST_Window : public GHOST_IWindow { * \section Interface inherited from GHOST_IWindow left for derived class * implementation. * virtual bool getValid() const = 0; - * virtual void setTitle(const STR_String& title) = 0; - * virtual void getTitle(STR_String& title) const = 0; + * virtual void setTitle(const char * title) = 0; + * virtual std::string getTitle() const = 0; * virtual void getWindowBounds(GHOST_Rect& bounds) const = 0; * virtual void getClientBounds(GHOST_Rect& bounds) const = 0; * virtual GHOST_TSuccess setClientWidth(GHOST_TUns32 width) = 0; diff --git a/intern/ghost/intern/GHOST_WindowCocoa.h b/intern/ghost/intern/GHOST_WindowCocoa.h index efa418deee2..15429eab5db 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.h +++ b/intern/ghost/intern/GHOST_WindowCocoa.h @@ -30,7 +30,6 @@ #endif // __APPLE__ #include "GHOST_Window.h" -#include "STR_String.h" @class CAMetalLayer; @class CocoaMetalView; @@ -58,7 +57,7 @@ class GHOST_WindowCocoa : public GHOST_Window { * \param stereoVisual Stereo visual for quad buffered stereo. */ GHOST_WindowCocoa(GHOST_SystemCocoa *systemCocoa, - const STR_String &title, + const char *title, GHOST_TInt32 left, GHOST_TInt32 bottom, GHOST_TUns32 width, @@ -92,13 +91,12 @@ class GHOST_WindowCocoa : public GHOST_Window { * Sets the title displayed in the title bar. * \param title The title to display in the title bar. */ - void setTitle(const STR_String &title); - + void setTitle(const char *title); /** * Returns the title displayed in the title bar. * \param title The title displayed in the title bar. */ - void getTitle(STR_String &title) const; + std::string getTitle() const; /** * Returns the window rectangle dimensions. diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm index 10ab05a0de1..05adc41cb8e 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.mm +++ b/intern/ghost/intern/GHOST_WindowCocoa.mm @@ -291,7 +291,7 @@ /* clang-format on */ GHOST_WindowCocoa::GHOST_WindowCocoa(GHOST_SystemCocoa *systemCocoa, - const STR_String &title, + const char *title, GHOST_TInt32 left, GHOST_TInt32 bottom, GHOST_TUns32 width, @@ -482,7 +482,7 @@ void *GHOST_WindowCocoa::getOSWindow() const return (void *)m_window; } -void GHOST_WindowCocoa::setTitle(const STR_String &title) +void GHOST_WindowCocoa::setTitle(const char *title) { GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setTitle(): window invalid"); NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; @@ -524,7 +524,7 @@ void GHOST_WindowCocoa::setTitle(const STR_String &title) [pool drain]; } -void GHOST_WindowCocoa::getTitle(STR_String &title) const +std::string GHOST_WindowCocoa::getTitle() const { GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getTitle(): window invalid"); @@ -532,11 +532,14 @@ void GHOST_WindowCocoa::getTitle(STR_String &title) const NSString *windowTitle = [m_window title]; + std::string title; if (windowTitle != nil) { title = [windowTitle UTF8String]; } [pool drain]; + + return title; } void GHOST_WindowCocoa::getWindowBounds(GHOST_Rect &bounds) const diff --git a/intern/ghost/intern/GHOST_WindowNULL.h b/intern/ghost/intern/GHOST_WindowNULL.h index db40075e6ca..e1aa0cb7f13 100644 --- a/intern/ghost/intern/GHOST_WindowNULL.h +++ b/intern/ghost/intern/GHOST_WindowNULL.h @@ -26,7 +26,6 @@ #include <map> -class STR_String; class GHOST_SystemNULL; class GHOST_WindowNULL : public GHOST_Window { @@ -37,7 +36,7 @@ class GHOST_WindowNULL : public GHOST_Window { } GHOST_WindowNULL(GHOST_SystemNULL *system, - const STR_String &title, + const char *title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, @@ -83,12 +82,12 @@ class GHOST_WindowNULL : public GHOST_Window { { return true; } - void setTitle(const STR_String &title) + void setTitle(const char *title) { /* nothing */ } - void getTitle(STR_String &title) const + std::string getTitle() const { - title = "untitled"; + return "untitled"; } void getWindowBounds(GHOST_Rect &bounds) const { diff --git a/intern/ghost/intern/GHOST_WindowSDL.cpp b/intern/ghost/intern/GHOST_WindowSDL.cpp index e8d129f45fe..dcb1ab8c78c 100644 --- a/intern/ghost/intern/GHOST_WindowSDL.cpp +++ b/intern/ghost/intern/GHOST_WindowSDL.cpp @@ -27,7 +27,7 @@ #include <assert.h> GHOST_WindowSDL::GHOST_WindowSDL(GHOST_SystemSDL *system, - const STR_String &title, + const char *title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, @@ -148,14 +148,14 @@ bool GHOST_WindowSDL::getValid() const return GHOST_Window::getValid() && m_valid_setup; } -void GHOST_WindowSDL::setTitle(const STR_String &title) +void GHOST_WindowSDL::setTitle(const char *title) { - SDL_SetWindowTitle(m_sdl_win, title.ReadPtr()); + SDL_SetWindowTitle(m_sdl_win, title); } -void GHOST_WindowSDL::getTitle(STR_String &title) const +std::string GHOST_WindowSDL::getTitle() const { - title = SDL_GetWindowTitle(m_sdl_win); + return SDL_GetWindowTitle(m_sdl_win); } void GHOST_WindowSDL::getWindowBounds(GHOST_Rect &bounds) const diff --git a/intern/ghost/intern/GHOST_WindowSDL.h b/intern/ghost/intern/GHOST_WindowSDL.h index eadd1b7df9d..5039c742c9d 100644 --- a/intern/ghost/intern/GHOST_WindowSDL.h +++ b/intern/ghost/intern/GHOST_WindowSDL.h @@ -35,7 +35,6 @@ extern "C" { # error "SDL 2.0 or newer is needed to build with Ghost" #endif -class STR_String; class GHOST_SystemSDL; class GHOST_WindowSDL : public GHOST_Window { @@ -49,7 +48,7 @@ class GHOST_WindowSDL : public GHOST_Window { public: GHOST_WindowSDL(GHOST_SystemSDL *system, - const STR_String &title, + const char *title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, @@ -107,9 +106,9 @@ class GHOST_WindowSDL : public GHOST_Window { GHOST_TSuccess setWindowCursorVisibility(bool visible); - void setTitle(const STR_String &title); + void setTitle(const char *title); - void getTitle(STR_String &title) const; + std::string getTitle() const; GHOST_TSuccess setClientWidth(GHOST_TUns32 width); diff --git a/intern/ghost/intern/GHOST_WindowWayland.cpp b/intern/ghost/intern/GHOST_WindowWayland.cpp new file mode 100644 index 00000000000..0ea6f5f8ecb --- /dev/null +++ b/intern/ghost/intern/GHOST_WindowWayland.cpp @@ -0,0 +1,406 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup GHOST + */ + +#include "GHOST_WindowWayland.h" +#include "GHOST_SystemWayland.h" +#include "GHOST_WindowManager.h" + +#include "GHOST_Event.h" + +#include "GHOST_ContextEGL.h" +#include "GHOST_ContextNone.h" + +#include <wayland-egl.h> + +struct window_t { + GHOST_WindowWayland *w; + wl_surface *surface; + struct xdg_surface *xdg_surface; + struct xdg_toplevel *xdg_toplevel; + wl_egl_window *egl_window; + int32_t pending_width, pending_height; + bool is_maximised; + bool is_fullscreen; + bool is_active; + int32_t width, height; +}; + +/* -------------------------------------------------------------------- */ +/** \name Wayland Interface Callbacks + * + * These callbacks are registered for Wayland interfaces and called when + * an event is received from the compositor. + * \{ */ + +static void toplevel_configure( + void *data, xdg_toplevel * /*xdg_toplevel*/, int32_t width, int32_t height, wl_array *states) +{ + window_t *win = static_cast<window_t *>(data); + win->pending_width = width; + win->pending_height = height; + + win->is_maximised = false; + win->is_fullscreen = false; + win->is_active = false; + + /* Note that the macro 'wl_array_for_each' would typically be used to simplify this logic, + * however it's not compatible with C++, so perform casts instead. + * If this needs to be done more often we could define our own C++ compatible macro. */ + for (enum xdg_toplevel_state *state = static_cast<xdg_toplevel_state *>(states->data); + reinterpret_cast<uint8_t *>(state) < (static_cast<uint8_t *>(states->data) + states->size); + state++) { + switch (*state) { + case XDG_TOPLEVEL_STATE_MAXIMIZED: + win->is_maximised = true; + break; + case XDG_TOPLEVEL_STATE_FULLSCREEN: + win->is_fullscreen = true; + break; + case XDG_TOPLEVEL_STATE_ACTIVATED: + win->is_active = true; + break; + default: + break; + } + } +} + +static void toplevel_close(void *data, xdg_toplevel * /*xdg_toplevel*/) +{ + static_cast<window_t *>(data)->w->close(); +} + +static const xdg_toplevel_listener toplevel_listener = { + toplevel_configure, + toplevel_close, +}; + +static void surface_configure(void *data, xdg_surface *xdg_surface, uint32_t serial) +{ + window_t *win = static_cast<window_t *>(data); + + int w, h; + wl_egl_window_get_attached_size(win->egl_window, &w, &h); + if (win->pending_width != 0 && win->pending_height != 0 && win->pending_width != w && + win->pending_height != h) { + win->width = win->pending_width; + win->height = win->pending_height; + wl_egl_window_resize(win->egl_window, win->pending_width, win->pending_height, 0, 0); + win->pending_width = 0; + win->pending_height = 0; + win->w->notify_size(); + } + + if (win->is_active) { + win->w->activate(); + } + else { + win->w->deactivate(); + } + + xdg_surface_ack_configure(xdg_surface, serial); +} + +static const xdg_surface_listener surface_listener = { + surface_configure, +}; + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Ghost Implementation + * + * Wayland specific implementation of the GHOST_Window interface. + * \{ */ + +GHOST_TSuccess GHOST_WindowWayland::hasCursorShape(GHOST_TStandardCursor cursorShape) +{ + return m_system->hasCursorShape(cursorShape); +} + +GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system, + const char *title, + GHOST_TInt32 /*left*/, + GHOST_TInt32 /*top*/, + GHOST_TUns32 width, + GHOST_TUns32 height, + GHOST_TWindowState state, + const GHOST_IWindow *parentWindow, + GHOST_TDrawingContextType type, + const bool stereoVisual, + const bool exclusive) + : GHOST_Window(width, height, state, stereoVisual, exclusive), + m_system(system), + w(new window_t) +{ + w->w = this; + + w->width = int32_t(width); + w->height = int32_t(height); + + /* Window surfaces. */ + w->surface = wl_compositor_create_surface(m_system->compositor()); + w->egl_window = wl_egl_window_create(w->surface, int(width), int(height)); + + w->xdg_surface = xdg_wm_base_get_xdg_surface(m_system->shell(), w->surface); + w->xdg_toplevel = xdg_surface_get_toplevel(w->xdg_surface); + + wl_surface_set_user_data(w->surface, this); + + xdg_surface_add_listener(w->xdg_surface, &surface_listener, w); + xdg_toplevel_add_listener(w->xdg_toplevel, &toplevel_listener, w); + + if (parentWindow) { + xdg_toplevel_set_parent( + w->xdg_toplevel, dynamic_cast<const GHOST_WindowWayland *>(parentWindow)->w->xdg_toplevel); + } + + /* Call top-level callbacks. */ + wl_surface_commit(w->surface); + wl_display_roundtrip(m_system->display()); + + setState(state); + + setTitle(title); + + /* EGL context. */ + if (setDrawingContextType(type) == GHOST_kFailure) { + GHOST_PRINT("Failed to create EGL context" << std::endl); + } +} + +GHOST_TSuccess GHOST_WindowWayland::close() +{ + return m_system->pushEvent( + new GHOST_Event(m_system->getMilliSeconds(), GHOST_kEventWindowClose, this)); +} + +GHOST_TSuccess GHOST_WindowWayland::activate() +{ + if (m_system->getWindowManager()->setActiveWindow(this) == GHOST_kFailure) { + return GHOST_kFailure; + } + return m_system->pushEvent( + new GHOST_Event(m_system->getMilliSeconds(), GHOST_kEventWindowActivate, this)); +} + +GHOST_TSuccess GHOST_WindowWayland::deactivate() +{ + m_system->getWindowManager()->setWindowInactive(this); + return m_system->pushEvent( + new GHOST_Event(m_system->getMilliSeconds(), GHOST_kEventWindowDeactivate, this)); +} + +GHOST_TSuccess GHOST_WindowWayland::notify_size() +{ + return m_system->pushEvent( + new GHOST_Event(m_system->getMilliSeconds(), GHOST_kEventWindowSize, this)); +} + +GHOST_TSuccess GHOST_WindowWayland::setWindowCursorGrab(GHOST_TGrabCursorMode mode) +{ + return m_system->setCursorGrab(mode, w->surface); +} + +GHOST_TSuccess GHOST_WindowWayland::setWindowCursorShape(GHOST_TStandardCursor shape) +{ + const GHOST_TSuccess ok = m_system->setCursorShape(shape); + m_cursorShape = (ok == GHOST_kSuccess) ? shape : GHOST_kStandardCursorDefault; + return ok; +} + +GHOST_TSuccess GHOST_WindowWayland::setWindowCustomCursorShape(GHOST_TUns8 *bitmap, + GHOST_TUns8 *mask, + int sizex, + int sizey, + int hotX, + int hotY, + bool canInvertColor) +{ + return m_system->setCustomCursorShape(bitmap, mask, sizex, sizey, hotX, hotY, canInvertColor); +} + +void GHOST_WindowWayland::setTitle(const char *title) +{ + xdg_toplevel_set_title(w->xdg_toplevel, title); + xdg_toplevel_set_app_id(w->xdg_toplevel, title); + this->title = title; +} + +std::string GHOST_WindowWayland::getTitle() const +{ + return this->title.empty() ? "untitled" : this->title; +} + +void GHOST_WindowWayland::getWindowBounds(GHOST_Rect &bounds) const +{ + getClientBounds(bounds); +} + +void GHOST_WindowWayland::getClientBounds(GHOST_Rect &bounds) const +{ + bounds.set(0, 0, w->width, w->height); +} + +GHOST_TSuccess GHOST_WindowWayland::setClientWidth(GHOST_TUns32 width) +{ + return setClientSize(width, GHOST_TUns32(w->height)); +} + +GHOST_TSuccess GHOST_WindowWayland::setClientHeight(GHOST_TUns32 height) +{ + return setClientSize(GHOST_TUns32(w->width), height); +} + +GHOST_TSuccess GHOST_WindowWayland::setClientSize(GHOST_TUns32 width, GHOST_TUns32 height) +{ + wl_egl_window_resize(w->egl_window, int(width), int(height), 0, 0); + return GHOST_kSuccess; +} + +void GHOST_WindowWayland::screenToClient(GHOST_TInt32 inX, + GHOST_TInt32 inY, + GHOST_TInt32 &outX, + GHOST_TInt32 &outY) const +{ + outX = inX; + outY = inY; +} + +void GHOST_WindowWayland::clientToScreen(GHOST_TInt32 inX, + GHOST_TInt32 inY, + GHOST_TInt32 &outX, + GHOST_TInt32 &outY) const +{ + outX = inX; + outY = inY; +} + +GHOST_WindowWayland::~GHOST_WindowWayland() +{ + releaseNativeHandles(); + + wl_egl_window_destroy(w->egl_window); + xdg_toplevel_destroy(w->xdg_toplevel); + xdg_surface_destroy(w->xdg_surface); + wl_surface_destroy(w->surface); + + delete w; +} + +GHOST_TSuccess GHOST_WindowWayland::setWindowCursorVisibility(bool visible) +{ + return m_system->setCursorVisibility(visible); +} + +GHOST_TSuccess GHOST_WindowWayland::setState(GHOST_TWindowState state) +{ + switch (state) { + case GHOST_kWindowStateNormal: + /* Unset states. */ + switch (getState()) { + case GHOST_kWindowStateMaximized: + xdg_toplevel_unset_maximized(w->xdg_toplevel); + break; + case GHOST_kWindowStateFullScreen: + xdg_toplevel_unset_fullscreen(w->xdg_toplevel); + break; + default: + break; + } + break; + case GHOST_kWindowStateMaximized: + xdg_toplevel_set_maximized(w->xdg_toplevel); + break; + case GHOST_kWindowStateMinimized: + xdg_toplevel_set_minimized(w->xdg_toplevel); + break; + case GHOST_kWindowStateFullScreen: + xdg_toplevel_set_fullscreen(w->xdg_toplevel, nullptr); + break; + case GHOST_kWindowStateEmbedded: + return GHOST_kFailure; + } + return GHOST_kSuccess; +} + +GHOST_TWindowState GHOST_WindowWayland::getState() const +{ + if (w->is_fullscreen) { + return GHOST_kWindowStateFullScreen; + } + else if (w->is_maximised) { + return GHOST_kWindowStateMaximized; + } + else { + return GHOST_kWindowStateNormal; + } +} + +GHOST_TSuccess GHOST_WindowWayland::invalidate() +{ + return GHOST_kSuccess; +} + +GHOST_TSuccess GHOST_WindowWayland::setOrder(GHOST_TWindowOrder /*order*/) +{ + return GHOST_kSuccess; +} + +GHOST_TSuccess GHOST_WindowWayland::beginFullScreen() const +{ + xdg_toplevel_set_fullscreen(w->xdg_toplevel, nullptr); + return GHOST_kSuccess; +} + +GHOST_TSuccess GHOST_WindowWayland::endFullScreen() const +{ + xdg_toplevel_unset_fullscreen(w->xdg_toplevel); + return GHOST_kSuccess; +} + +/** + * \param type The type of rendering context create. + * \return Indication of success. + */ +GHOST_Context *GHOST_WindowWayland::newDrawingContext(GHOST_TDrawingContextType type) +{ + GHOST_Context *context; + switch (type) { + case GHOST_kDrawingContextTypeNone: + context = new GHOST_ContextNone(m_wantStereoVisual); + break; + case GHOST_kDrawingContextTypeOpenGL: + context = new GHOST_ContextEGL(m_wantStereoVisual, + EGLNativeWindowType(w->egl_window), + EGLNativeDisplayType(m_system->display()), + EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT, + 3, + 3, + GHOST_OPENGL_EGL_CONTEXT_FLAGS, + GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY, + EGL_OPENGL_API); + break; + } + + return (context->initializeDrawingContext() == GHOST_kSuccess) ? context : nullptr; +} + +/** \} */ diff --git a/intern/ghost/intern/GHOST_WindowWayland.h b/intern/ghost/intern/GHOST_WindowWayland.h new file mode 100644 index 00000000000..39c35f77d7d --- /dev/null +++ b/intern/ghost/intern/GHOST_WindowWayland.h @@ -0,0 +1,121 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup GHOST + * + * Declaration of GHOST_WindowWayland class. + */ + +#ifndef __GHOST_WINDOWWAYLAND_H__ +#define __GHOST_WINDOWWAYLAND_H__ + +#include "GHOST_Window.h" + +class GHOST_SystemWayland; + +struct window_t; + +class GHOST_WindowWayland : public GHOST_Window { + public: + GHOST_TSuccess hasCursorShape(GHOST_TStandardCursor cursorShape) override; + + GHOST_WindowWayland(GHOST_SystemWayland *system, + const char *title, + GHOST_TInt32 left, + GHOST_TInt32 top, + GHOST_TUns32 width, + GHOST_TUns32 height, + GHOST_TWindowState state, + const GHOST_IWindow *parentWindow, + GHOST_TDrawingContextType type, + const bool stereoVisual, + const bool exclusive); + + ~GHOST_WindowWayland() override; + + GHOST_TSuccess close(); + + GHOST_TSuccess activate(); + + GHOST_TSuccess deactivate(); + + GHOST_TSuccess notify_size(); + + protected: + GHOST_TSuccess setWindowCursorGrab(GHOST_TGrabCursorMode mode) override; + + GHOST_TSuccess setWindowCursorShape(GHOST_TStandardCursor shape) override; + + GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 *bitmap, + GHOST_TUns8 *mask, + int sizex, + int sizey, + int hotX, + int hotY, + bool canInvertColor) override; + + void setTitle(const char *title) override; + + std::string getTitle() const override; + + void getWindowBounds(GHOST_Rect &bounds) const override; + + void getClientBounds(GHOST_Rect &bounds) const override; + + GHOST_TSuccess setClientWidth(GHOST_TUns32 width) override; + + GHOST_TSuccess setClientHeight(GHOST_TUns32 height) override; + + GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height) override; + + void screenToClient(GHOST_TInt32 inX, + GHOST_TInt32 inY, + GHOST_TInt32 &outX, + GHOST_TInt32 &outY) const override; + + void clientToScreen(GHOST_TInt32 inX, + GHOST_TInt32 inY, + GHOST_TInt32 &outX, + GHOST_TInt32 &outY) const override; + + GHOST_TSuccess setWindowCursorVisibility(bool visible) override; + + GHOST_TSuccess setState(GHOST_TWindowState state) override; + + GHOST_TWindowState getState() const override; + + GHOST_TSuccess invalidate() override; + + GHOST_TSuccess setOrder(GHOST_TWindowOrder order) override; + + GHOST_TSuccess beginFullScreen() const override; + + GHOST_TSuccess endFullScreen() const override; + + private: + GHOST_SystemWayland *m_system; + struct window_t *w; + std::string title; + + /** + * \param type The type of rendering context create. + * \return Indication of success. + */ + GHOST_Context *newDrawingContext(GHOST_TDrawingContextType type) override; +}; + +#endif // __GHOST_WINDOWWAYLAND_H__ diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp index 8b95cdd6351..55525157753 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.cpp +++ b/intern/ghost/intern/GHOST_WindowWin32.cpp @@ -59,7 +59,7 @@ __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; } GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system, - const STR_String &title, + const char *title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, @@ -158,7 +158,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system, height = rect.bottom - rect.top; } - wchar_t *title_16 = alloc_utf16_from_8((char *)(const char *)title, 0); + wchar_t *title_16 = alloc_utf16_from_8((char *)title, 0); m_hWnd = ::CreateWindowW(s_windowClassName, // pointer to registered class name title_16, // pointer to window name wintype, // window style @@ -173,7 +173,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system, free(title_16); } else { - wchar_t *title_16 = alloc_utf16_from_8((char *)(const char *)title, 0); + wchar_t *title_16 = alloc_utf16_from_8((char *)title, 0); m_hWnd = ::CreateWindowW(s_windowClassName, // pointer to registered class name title_16, // pointer to window name WS_MAXIMIZE, // window style @@ -430,19 +430,18 @@ HWND GHOST_WindowWin32::getHWND() const return m_hWnd; } -void GHOST_WindowWin32::setTitle(const STR_String &title) +void GHOST_WindowWin32::setTitle(const char *title) { - wchar_t *title_16 = alloc_utf16_from_8((char *)(const char *)title, 0); + wchar_t *title_16 = alloc_utf16_from_8((char *)title, 0); ::SetWindowTextW(m_hWnd, (wchar_t *)title_16); free(title_16); } -void GHOST_WindowWin32::getTitle(STR_String &title) const +std::string GHOST_WindowWin32::getTitle() const { char buf[s_maxTitleLength]; /*CHANGE + never used yet*/ ::GetWindowText(m_hWnd, buf, s_maxTitleLength); - STR_String temp(buf); - title = buf; + return std::string(buf); } void GHOST_WindowWin32::getWindowBounds(GHOST_Rect &bounds) const diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h index 489d3032552..dbed7c5ee5f 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.h +++ b/intern/ghost/intern/GHOST_WindowWin32.h @@ -261,7 +261,7 @@ class GHOST_WindowWin32 : public GHOST_Window { * \param parentWindowHwnd */ GHOST_WindowWin32(GHOST_SystemWin32 *system, - const STR_String &title, + const char *title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, @@ -296,13 +296,13 @@ class GHOST_WindowWin32 : public GHOST_Window { * Sets the title displayed in the title bar. * \param title The title to display in the title bar. */ - void setTitle(const STR_String &title); + void setTitle(const char *title); /** * Returns the title displayed in the title bar. - * \param title The title displayed in the title bar. + * \return The title displayed in the title bar. */ - void getTitle(STR_String &title) const; + std::string getTitle() const; /** * Returns the window rectangle dimensions. diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp index db9f6846b11..691f1790a2d 100644 --- a/intern/ghost/intern/GHOST_WindowX11.cpp +++ b/intern/ghost/intern/GHOST_WindowX11.cpp @@ -33,7 +33,6 @@ #include "GHOST_IconX11.h" #include "GHOST_SystemX11.h" #include "GHOST_WindowX11.h" -#include "STR_String.h" #ifdef WITH_XDND # include "GHOST_DropTargetX11.h" @@ -61,6 +60,7 @@ #include <unistd.h> #include <algorithm> +#include <limits.h> #include <math.h> #include <string> @@ -212,7 +212,7 @@ static XVisualInfo *x11_visualinfo_from_glx(Display *display, GHOST_WindowX11::GHOST_WindowX11(GHOST_SystemX11 *system, Display *display, - const STR_String &title, + const char *title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, @@ -414,9 +414,9 @@ GHOST_WindowX11::GHOST_WindowX11(GHOST_SystemX11 *system, /* XClassHint, title */ { XClassHint *xclasshint = XAllocClassHint(); - const int len = title.Length() + 1; + const int len = strlen(title) + 1; char *wmclass = (char *)malloc(sizeof(char) * len); - memcpy(wmclass, title.ReadPtr(), len * sizeof(char)); + memcpy(wmclass, title, len * sizeof(char)); xclasshint->res_name = wmclass; xclasshint->res_class = wmclass; XSetClassHint(m_display, m_window, xclasshint); @@ -617,7 +617,7 @@ bool GHOST_WindowX11::getValid() const return GHOST_Window::getValid() && m_valid_setup; } -void GHOST_WindowX11::setTitle(const STR_String &title) +void GHOST_WindowX11::setTitle(const char *title) { Atom name = XInternAtom(m_display, "_NET_WM_NAME", 0); Atom utf8str = XInternAtom(m_display, "UTF8_STRING", 0); @@ -627,8 +627,8 @@ void GHOST_WindowX11::setTitle(const STR_String &title) utf8str, 8, PropModeReplace, - (const unsigned char *)title.ReadPtr(), - title.Length()); + (const unsigned char *)title, + strlen(title)); /* This should convert to valid x11 string * and getTitle would need matching change */ @@ -637,13 +637,14 @@ void GHOST_WindowX11::setTitle(const STR_String &title) XFlush(m_display); } -void GHOST_WindowX11::getTitle(STR_String &title) const +std::string GHOST_WindowX11::getTitle() const { char *name = NULL; XFetchName(m_display, m_window, &name); - title = name ? name : "untitled"; + std::string title = name ? name : "untitled"; XFree(name); + return title; } void GHOST_WindowX11::getWindowBounds(GHOST_Rect &bounds) const diff --git a/intern/ghost/intern/GHOST_WindowX11.h b/intern/ghost/intern/GHOST_WindowX11.h index 4704cb45e58..4232ff40b52 100644 --- a/intern/ghost/intern/GHOST_WindowX11.h +++ b/intern/ghost/intern/GHOST_WindowX11.h @@ -37,7 +37,6 @@ #include <map> -class STR_String; class GHOST_SystemX11; #ifdef WITH_XDND @@ -69,7 +68,7 @@ class GHOST_WindowX11 : public GHOST_Window { */ GHOST_WindowX11(GHOST_SystemX11 *system, Display *display, - const STR_String &title, + const char *title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, @@ -85,9 +84,9 @@ class GHOST_WindowX11 : public GHOST_Window { bool getValid() const; - void setTitle(const STR_String &title); + void setTitle(const char *title); - void getTitle(STR_String &title) const; + std::string getTitle() const; void getWindowBounds(GHOST_Rect &bounds) const; diff --git a/intern/ghost/intern/GHOST_XrGraphicsBinding.cpp b/intern/ghost/intern/GHOST_XrGraphicsBinding.cpp index 60b3b06f6a8..5e30502f7ff 100644 --- a/intern/ghost/intern/GHOST_XrGraphicsBinding.cpp +++ b/intern/ghost/intern/GHOST_XrGraphicsBinding.cpp @@ -22,7 +22,7 @@ #include <list> #include <sstream> -#if defined(WITH_X11) +#if defined(WITH_GHOST_X11) # include "GHOST_ContextGLX.h" #elif defined(WIN32) # include "GHOST_ContextD3D.h" @@ -68,7 +68,7 @@ class GHOST_XrGraphicsBindingOpenGL : public GHOST_IXrGraphicsBinding { XrSystemId system_id, std::string *r_requirement_info) const override { -#if defined(WITH_X11) +#if defined(WITH_GHOST_X11) GHOST_ContextGLX *ctx_gl = static_cast<GHOST_ContextGLX *>(ghost_ctx); #else GHOST_ContextWGL *ctx_gl = static_cast<GHOST_ContextWGL *>(ghost_ctx); @@ -107,7 +107,7 @@ class GHOST_XrGraphicsBindingOpenGL : public GHOST_IXrGraphicsBinding { void initFromGhostContext(GHOST_Context *ghost_ctx) override { -#if defined(WITH_X11) +#if defined(WITH_GHOST_X11) GHOST_ContextGLX *ctx_glx = static_cast<GHOST_ContextGLX *>(ghost_ctx); XVisualInfo *visual_info = glXGetVisualFromFBConfig(ctx_glx->m_display, ctx_glx->m_fbconfig); diff --git a/intern/ghost/intern/GHOST_Xr_openxr_includes.h b/intern/ghost/intern/GHOST_Xr_openxr_includes.h index 925d6037750..9cac43b1549 100644 --- a/intern/ghost/intern/GHOST_Xr_openxr_includes.h +++ b/intern/ghost/intern/GHOST_Xr_openxr_includes.h @@ -42,7 +42,7 @@ #ifdef XR_USE_GRAPHICS_API_D3D12 # include <d3d12.h> #endif -#ifdef WITH_X11 +#ifdef WITH_GHOST_X11 # include <GL/glxew.h> #endif diff --git a/intern/ghost/test/CMakeLists.txt b/intern/ghost/test/CMakeLists.txt index eda41eb9c1a..b6e3c0ecf5f 100644 --- a/intern/ghost/test/CMakeLists.txt +++ b/intern/ghost/test/CMakeLists.txt @@ -85,8 +85,9 @@ endif() # Libraries if(UNIX AND NOT APPLE) - set(WITH_X11 ON) + set(WITH_GHOST_X11 ON) endif() + # for now... default to this add_definitions(-DWITH_GL_PROFILE_COMPAT) # BLF needs this to ignore GPU library diff --git a/intern/ghost/test/gears/GHOST_Test.cpp b/intern/ghost/test/gears/GHOST_Test.cpp index a554bfeebef..c9c497aacb4 100644 --- a/intern/ghost/test/gears/GHOST_Test.cpp +++ b/intern/ghost/test/gears/GHOST_Test.cpp @@ -27,6 +27,7 @@ #include <iostream> #include <math.h> +#include <string> #if defined(WIN32) || defined(__APPLE__) # ifdef WIN32 @@ -43,7 +44,6 @@ #endif // defined(WIN32) || defined(__APPLE__) #include "GHOST_Rect.h" -#include "STR_String.h" #include "GHOST_IEvent.h" #include "GHOST_IEventConsumer.h" @@ -427,8 +427,7 @@ Application::Application(GHOST_ISystem *system) fApp = this; // Create the main window - STR_String title1("gears - main window"); - m_mainWindow = system->createWindow(title1, + m_mainWindow = system->createWindow("gears - main window", 10, 64, 320, @@ -443,8 +442,7 @@ Application::Application(GHOST_ISystem *system) } // Create a secondary window - STR_String title2("gears - secondary window"); - m_secondaryWindow = system->createWindow(title2, + m_secondaryWindow = system->createWindow("gears - secondary window", 340, 64, 320, @@ -598,8 +596,7 @@ bool Application::processEvent(GHOST_IEvent *event) case GHOST_kKeyW: if (m_mainWindow) { - STR_String title; - m_mainWindow->getTitle(title); + std::string title = m_mainWindow->getTitle(); title += "-"; m_mainWindow->setTitle(title); } diff --git a/intern/libmv/intern/camera_intrinsics.cc b/intern/libmv/intern/camera_intrinsics.cc index 89e3d0d1178..554c4350b0a 100644 --- a/intern/libmv/intern/camera_intrinsics.cc +++ b/intern/libmv/intern/camera_intrinsics.cc @@ -24,6 +24,7 @@ using libmv::CameraIntrinsics; using libmv::DivisionCameraIntrinsics; using libmv::PolynomialCameraIntrinsics; +using libmv::NukeCameraIntrinsics; libmv_CameraIntrinsics *libmv_cameraIntrinsicsNew( const libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options) { @@ -55,6 +56,14 @@ libmv_CameraIntrinsics *libmv_cameraIntrinsicsCopy( *division_intrinsics); break; } + case libmv::DISTORTION_MODEL_NUKE: + { + const NukeCameraIntrinsics *nuke_intrinsics = + static_cast<const NukeCameraIntrinsics*>(orig_intrinsics); + new_intrinsics = LIBMV_OBJECT_NEW(NukeCameraIntrinsics, + *nuke_intrinsics); + break; + } default: assert(!"Unknown distortion model"); } @@ -136,6 +145,25 @@ void libmv_cameraIntrinsicsUpdate( break; } + case LIBMV_DISTORTION_MODEL_NUKE: + { + assert(camera_intrinsics->GetDistortionModelType() == + libmv::DISTORTION_MODEL_NUKE); + + NukeCameraIntrinsics *nuke_intrinsics = + (NukeCameraIntrinsics *) camera_intrinsics; + + double k1 = libmv_camera_intrinsics_options->nuke_k1; + double k2 = libmv_camera_intrinsics_options->nuke_k2; + + if (nuke_intrinsics->k1() != k1 || + nuke_intrinsics->k2() != k2) { + nuke_intrinsics->SetDistortion(k1, k2); + } + + break; + } + default: assert(!"Unknown distortion model"); } @@ -189,6 +217,17 @@ void libmv_cameraIntrinsicsExtractOptions( break; } + case libmv::DISTORTION_MODEL_NUKE: + { + const NukeCameraIntrinsics *nuke_intrinsics = + static_cast<const NukeCameraIntrinsics *>(camera_intrinsics); + camera_intrinsics_options->distortion_model = + LIBMV_DISTORTION_MODEL_NUKE; + camera_intrinsics_options->nuke_k1 = nuke_intrinsics->k1(); + camera_intrinsics_options->nuke_k2 = nuke_intrinsics->k2(); + break; + } + default: assert(!"Unknown distortion model"); } @@ -316,6 +355,17 @@ static void libmv_cameraIntrinsicsFillFromOptions( break; } + case LIBMV_DISTORTION_MODEL_NUKE: + { + NukeCameraIntrinsics *nuke_intrinsics = + static_cast<NukeCameraIntrinsics*>(camera_intrinsics); + + nuke_intrinsics->SetDistortion( + camera_intrinsics_options->nuke_k1, + camera_intrinsics_options->nuke_k2); + break; + } + default: assert(!"Unknown distortion model"); } @@ -331,6 +381,9 @@ CameraIntrinsics* libmv_cameraIntrinsicsCreateFromOptions( case LIBMV_DISTORTION_MODEL_DIVISION: camera_intrinsics = LIBMV_OBJECT_NEW(DivisionCameraIntrinsics); break; + case LIBMV_DISTORTION_MODEL_NUKE: + camera_intrinsics = LIBMV_OBJECT_NEW(NukeCameraIntrinsics); + break; default: assert(!"Unknown distortion model"); } diff --git a/intern/libmv/intern/camera_intrinsics.h b/intern/libmv/intern/camera_intrinsics.h index 40a5826a9c4..b3d259893bd 100644 --- a/intern/libmv/intern/camera_intrinsics.h +++ b/intern/libmv/intern/camera_intrinsics.h @@ -29,6 +29,7 @@ typedef struct libmv_CameraIntrinsics libmv_CameraIntrinsics; enum { LIBMV_DISTORTION_MODEL_POLYNOMIAL = 0, LIBMV_DISTORTION_MODEL_DIVISION = 1, + LIBMV_DISTORTION_MODEL_NUKE = 2, }; typedef struct libmv_CameraIntrinsicsOptions { @@ -45,6 +46,9 @@ typedef struct libmv_CameraIntrinsicsOptions { // Division distortion model. double division_k1, division_k2; + + // Nuke distortion model. + double nuke_k1, nuke_k2; } libmv_CameraIntrinsicsOptions; libmv_CameraIntrinsics *libmv_cameraIntrinsicsNew( diff --git a/intern/libmv/libmv/simple_pipeline/bundle.cc b/intern/libmv/libmv/simple_pipeline/bundle.cc index e61650fb371..a70fdbc9888 100644 --- a/intern/libmv/libmv/simple_pipeline/bundle.cc +++ b/intern/libmv/libmv/simple_pipeline/bundle.cc @@ -66,18 +66,221 @@ enum { namespace { -// Cost functor which computes reprojection error of 3D point X -// on camera defined by angle-axis rotation and it's translation -// (which are in the same block due to optimization reasons). +bool NeedUseInvertIntrinsicsPipeline(const CameraIntrinsics *intrinsics) { + const DistortionModelType distortion_model = + intrinsics->GetDistortionModelType(); + return (distortion_model == DISTORTION_MODEL_NUKE); +} + +// Apply distortion model (distort the input) on the input point in the +// normalized space to get distorted coordinate in the image space. +// +// Using intrinsics values from the parameter block, which makes this function +// suitable for use from a cost functor. +// +// Only use for distortion models which are analytically defined for their +// Apply() function. +// +// The invariant_intrinsics are used to access intrinsics which are never +// packed into parameter block: for example, distortion model type and image +// dimension. +template<typename T> +void ApplyDistortionModelUsingIntrinsicsBlock( + const CameraIntrinsics *invariant_intrinsics, + const T* const intrinsics_block, + const T& normalized_x, const T& normalized_y, + T* distorted_x, T* distorted_y) { + // Unpack the intrinsics. + const T& focal_length = intrinsics_block[OFFSET_FOCAL_LENGTH]; + const T& principal_point_x = intrinsics_block[OFFSET_PRINCIPAL_POINT_X]; + const T& principal_point_y = intrinsics_block[OFFSET_PRINCIPAL_POINT_Y]; + + // TODO(keir): Do early bailouts for zero distortion; these are expensive + // jet operations. + switch (invariant_intrinsics->GetDistortionModelType()) { + case DISTORTION_MODEL_POLYNOMIAL: + { + const T& k1 = intrinsics_block[OFFSET_K1]; + const T& k2 = intrinsics_block[OFFSET_K2]; + const T& k3 = intrinsics_block[OFFSET_K3]; + const T& p1 = intrinsics_block[OFFSET_P1]; + const T& p2 = intrinsics_block[OFFSET_P2]; + + ApplyPolynomialDistortionModel(focal_length, + focal_length, + principal_point_x, + principal_point_y, + k1, k2, k3, + p1, p2, + normalized_x, normalized_y, + distorted_x, distorted_y); + return; + } + + case DISTORTION_MODEL_DIVISION: + { + const T& k1 = intrinsics_block[OFFSET_K1]; + const T& k2 = intrinsics_block[OFFSET_K2]; + + ApplyDivisionDistortionModel(focal_length, + focal_length, + principal_point_x, + principal_point_y, + k1, k2, + normalized_x, normalized_y, + distorted_x, distorted_y); + return; + } + + case DISTORTION_MODEL_NUKE: + { + LOG(FATAL) << "Unsupported distortion model."; + return; + } + } + + LOG(FATAL) << "Unknown distortion model."; +} + +// Invert distortion model (undistort the input) on the input point in the +// image space to get undistorted coordinate in the normalized space. +// +// Using intrinsics values from the parameter block, which makes this function +// suitable for use from a cost functor. +// +// Only use for distortion models which are analytically defined for their +// Invert() function. +// +// The invariant_intrinsics are used to access intrinsics which are never +// packed into parameter block: for example, distortion model type and image +// dimension. +template<typename T> +void InvertDistortionModelUsingIntrinsicsBlock( + const CameraIntrinsics *invariant_intrinsics, + const T* const intrinsics_block, + const T& image_x, const T& image_y, + T* normalized_x, T* normalized_y) { + // Unpack the intrinsics. + const T& focal_length = intrinsics_block[OFFSET_FOCAL_LENGTH]; + const T& principal_point_x = intrinsics_block[OFFSET_PRINCIPAL_POINT_X]; + const T& principal_point_y = intrinsics_block[OFFSET_PRINCIPAL_POINT_Y]; + + // TODO(keir): Do early bailouts for zero distortion; these are expensive + // jet operations. + switch (invariant_intrinsics->GetDistortionModelType()) { + case DISTORTION_MODEL_POLYNOMIAL: + case DISTORTION_MODEL_DIVISION: + LOG(FATAL) << "Unsupported distortion model."; + return; + + case DISTORTION_MODEL_NUKE: + { + const T& k1 = intrinsics_block[OFFSET_K1]; + const T& k2 = intrinsics_block[OFFSET_K2]; + + InvertNukeDistortionModel(focal_length, + focal_length, + principal_point_x, + principal_point_y, + invariant_intrinsics->image_width(), + invariant_intrinsics->image_height(), + k1, k2, + image_x, image_y, + normalized_x, normalized_y); + return; + } + } + + LOG(FATAL) << "Unknown distortion model."; +} + +template<typename T> +void NormalizedToImageSpace(const T* const intrinsics_block, + const T& normalized_x, const T& normalized_y, + T* image_x, T* image_y) { + // Unpack the intrinsics. + const T& focal_length = intrinsics_block[OFFSET_FOCAL_LENGTH]; + const T& principal_point_x = intrinsics_block[OFFSET_PRINCIPAL_POINT_X]; + const T& principal_point_y = intrinsics_block[OFFSET_PRINCIPAL_POINT_Y]; + + *image_x = normalized_x * focal_length + principal_point_x; + *image_y = normalized_y * focal_length + principal_point_y; +} + +// Cost functor which computes reprojection error of 3D point X on camera +// defined by angle-axis rotation and it's translation (which are in the same +// block due to optimization reasons). +// +// This functor can only be used for distortion models which have analytically +// defined Apply() function. +struct ReprojectionErrorApplyIntrinsics { + ReprojectionErrorApplyIntrinsics( + const CameraIntrinsics *invariant_intrinsics, + const double observed_distorted_x, + const double observed_distorted_y, + const double weight) + : invariant_intrinsics_(invariant_intrinsics), + observed_distorted_x_(observed_distorted_x), + observed_distorted_y_(observed_distorted_y), + weight_(weight) {} + + template <typename T> + bool operator()(const T* const intrinsics, + const T* const R_t, // Rotation denoted by angle axis + // followed with translation + const T* const X, // Point coordinates 3x1. + T* residuals) const { + // Compute projective coordinates: x = RX + t. + T x[3]; + + ceres::AngleAxisRotatePoint(R_t, X, x); + x[0] += R_t[3]; + x[1] += R_t[4]; + x[2] += R_t[5]; + + // Prevent points from going behind the camera. + if (x[2] < T(0)) { + return false; + } + + // Compute normalized coordinates: x /= x[2]. + T xn = x[0] / x[2]; + T yn = x[1] / x[2]; + + T predicted_distorted_x, predicted_distorted_y; + ApplyDistortionModelUsingIntrinsicsBlock( + invariant_intrinsics_, + intrinsics, + xn, yn, + &predicted_distorted_x, &predicted_distorted_y); + + // The error is the difference between the predicted and observed position. + residuals[0] = (predicted_distorted_x - T(observed_distorted_x_)) * weight_; + residuals[1] = (predicted_distorted_y - T(observed_distorted_y_)) * weight_; + return true; + } + + const CameraIntrinsics *invariant_intrinsics_; + const double observed_distorted_x_; + const double observed_distorted_y_; + const double weight_; +}; + +// Cost functor which computes reprojection error of 3D point X on camera +// defined by angle-axis rotation and it's translation (which are in the same +// block due to optimization reasons). // -// This functor uses a radial distortion model. -struct OpenCVReprojectionError { - OpenCVReprojectionError(const DistortionModelType distortion_model, - const double observed_x, - const double observed_y, - const double weight) - : distortion_model_(distortion_model), - observed_x_(observed_x), observed_y_(observed_y), +// This functor can only be used for distortion models which have analytically +// defined Invert() function. +struct ReprojectionErrorInvertIntrinsics { + ReprojectionErrorInvertIntrinsics( + const CameraIntrinsics *invariant_intrinsics, + const double observed_distorted_x, + const double observed_distorted_y, + const double weight) + : invariant_intrinsics_(invariant_intrinsics), + observed_distorted_x_(observed_distorted_x), + observed_distorted_y_(observed_distorted_y), weight_(weight) {} template <typename T> @@ -108,63 +311,37 @@ struct OpenCVReprojectionError { T xn = x[0] / x[2]; T yn = x[1] / x[2]; - T predicted_x, predicted_y; - - // Apply distortion to the normalized points to get (xd, yd). - // TODO(keir): Do early bailouts for zero distortion; these are expensive - // jet operations. - switch (distortion_model_) { - case DISTORTION_MODEL_POLYNOMIAL: - { - const T& k1 = intrinsics[OFFSET_K1]; - const T& k2 = intrinsics[OFFSET_K2]; - const T& k3 = intrinsics[OFFSET_K3]; - const T& p1 = intrinsics[OFFSET_P1]; - const T& p2 = intrinsics[OFFSET_P2]; - - ApplyPolynomialDistortionModel(focal_length, - focal_length, - principal_point_x, - principal_point_y, - k1, k2, k3, - p1, p2, - xn, yn, - &predicted_x, - &predicted_y); - break; - } - case DISTORTION_MODEL_DIVISION: - { - const T& k1 = intrinsics[OFFSET_K1]; - const T& k2 = intrinsics[OFFSET_K2]; + // Compute image space coordinate from normalized. + T predicted_x = focal_length * xn + principal_point_x; + T predicted_y = focal_length * yn + principal_point_y; - ApplyDivisionDistortionModel(focal_length, - focal_length, - principal_point_x, - principal_point_y, - k1, k2, - xn, yn, - &predicted_x, - &predicted_y); - break; - } - default: - LOG(FATAL) << "Unknown distortion model"; - } + T observed_undistorted_normalized_x, observed_undistorted_normalized_y; + InvertDistortionModelUsingIntrinsicsBlock( + invariant_intrinsics_, + intrinsics, + T(observed_distorted_x_), T(observed_distorted_y_), + &observed_undistorted_normalized_x, &observed_undistorted_normalized_y); + + T observed_undistorted_image_x, observed_undistorted_image_y; + NormalizedToImageSpace( + intrinsics, + observed_undistorted_normalized_x, observed_undistorted_normalized_y, + &observed_undistorted_image_x, &observed_undistorted_image_y); // The error is the difference between the predicted and observed position. - residuals[0] = (predicted_x - T(observed_x_)) * weight_; - residuals[1] = (predicted_y - T(observed_y_)) * weight_; + residuals[0] = (predicted_x - observed_undistorted_image_x) * weight_; + residuals[1] = (predicted_y - observed_undistorted_image_y) * weight_; + return true; } - const DistortionModelType distortion_model_; - const double observed_x_; - const double observed_y_; + const CameraIntrinsics *invariant_intrinsics_; + const double observed_distorted_x_; + const double observed_distorted_y_; const double weight_; }; -// Print a message to the log which camera intrinsics are gonna to be optimixed. +// Print a message to the log which camera intrinsics are gonna to be optimized. void BundleIntrinsicsLogMessage(const int bundle_intrinsics) { if (bundle_intrinsics == BUNDLE_NO_INTRINSICS) { LOG(INFO) << "Bundling only camera positions."; @@ -193,29 +370,29 @@ void BundleIntrinsicsLogMessage(const int bundle_intrinsics) { // Pack intrinsics from object to an array for easier // and faster minimization. void PackIntrinisicsIntoArray(const CameraIntrinsics &intrinsics, - double ceres_intrinsics[OFFSET_MAX]) { - ceres_intrinsics[OFFSET_FOCAL_LENGTH] = intrinsics.focal_length(); - ceres_intrinsics[OFFSET_PRINCIPAL_POINT_X] = intrinsics.principal_point_x(); - ceres_intrinsics[OFFSET_PRINCIPAL_POINT_Y] = intrinsics.principal_point_y(); + double intrinsics_block[OFFSET_MAX]) { + intrinsics_block[OFFSET_FOCAL_LENGTH] = intrinsics.focal_length(); + intrinsics_block[OFFSET_PRINCIPAL_POINT_X] = intrinsics.principal_point_x(); + intrinsics_block[OFFSET_PRINCIPAL_POINT_Y] = intrinsics.principal_point_y(); int num_distortion_parameters = intrinsics.num_distortion_parameters(); assert(num_distortion_parameters <= NUM_DISTORTION_COEFFICIENTS); const double *distortion_parameters = intrinsics.distortion_parameters(); for (int i = 0; i < num_distortion_parameters; ++i) { - ceres_intrinsics[FIRST_DISTORTION_COEFFICIENT + i] = + intrinsics_block[FIRST_DISTORTION_COEFFICIENT + i] = distortion_parameters[i]; } } // Unpack intrinsics back from an array to an object. -void UnpackIntrinsicsFromArray(const double ceres_intrinsics[OFFSET_MAX], +void UnpackIntrinsicsFromArray(const double intrinsics_block[OFFSET_MAX], CameraIntrinsics *intrinsics) { - intrinsics->SetFocalLength(ceres_intrinsics[OFFSET_FOCAL_LENGTH], - ceres_intrinsics[OFFSET_FOCAL_LENGTH]); + intrinsics->SetFocalLength(intrinsics_block[OFFSET_FOCAL_LENGTH], + intrinsics_block[OFFSET_FOCAL_LENGTH]); - intrinsics->SetPrincipalPoint(ceres_intrinsics[OFFSET_PRINCIPAL_POINT_X], - ceres_intrinsics[OFFSET_PRINCIPAL_POINT_Y]); + intrinsics->SetPrincipalPoint(intrinsics_block[OFFSET_PRINCIPAL_POINT_X], + intrinsics_block[OFFSET_PRINCIPAL_POINT_Y]); int num_distortion_parameters = intrinsics->num_distortion_parameters(); assert(num_distortion_parameters <= NUM_DISTORTION_COEFFICIENTS); @@ -223,7 +400,7 @@ void UnpackIntrinsicsFromArray(const double ceres_intrinsics[OFFSET_MAX], double *distortion_parameters = intrinsics->distortion_parameters(); for (int i = 0; i < num_distortion_parameters; ++i) { distortion_parameters[i] = - ceres_intrinsics[FIRST_DISTORTION_COEFFICIENT + i]; + intrinsics_block[FIRST_DISTORTION_COEFFICIENT + i]; } } @@ -302,68 +479,117 @@ void EuclideanBundlerPerformEvaluation(const Tracks &tracks, vector<Vec6> *all_cameras_R_t, ceres::Problem *problem, BundleEvaluation *evaluation) { - int max_track = tracks.MaxTrack(); - // Number of camera rotations equals to number of translation, - int num_cameras = all_cameras_R_t->size(); - int num_points = 0; - - vector<EuclideanPoint*> minimized_points; - for (int i = 0; i <= max_track; i++) { - EuclideanPoint *point = reconstruction->PointForTrack(i); - if (point) { - // We need to know whether the track is constant zero weight, - // and it so it wouldn't have parameter block in the problem. - // - // Getting all markers for track is not so bac currently since - // this code is only used by keyframe selection when there are - // not so much tracks and only 2 frames anyway. - vector<Marker> markera_of_track = tracks.MarkersForTrack(i); - for (int j = 0; j < markera_of_track.size(); j++) { - if (markera_of_track.at(j).weight != 0.0) { - minimized_points.push_back(point); - num_points++; - break; - } + int max_track = tracks.MaxTrack(); + // Number of camera rotations equals to number of translation, + int num_cameras = all_cameras_R_t->size(); + int num_points = 0; + + vector<EuclideanPoint*> minimized_points; + for (int i = 0; i <= max_track; i++) { + EuclideanPoint *point = reconstruction->PointForTrack(i); + if (point) { + // We need to know whether the track is a constant zero weight. + // If it is so it wouldn't have a parameter block in the problem. + // + // Usually getting all markers of a track is considered slow, but this + // code is only used by the keyframe selection code where there aren't + // that many tracks in the storage and there are only 2 frames for each + // of the tracks. + vector<Marker> markera_of_track = tracks.MarkersForTrack(i); + for (int j = 0; j < markera_of_track.size(); j++) { + if (markera_of_track.at(j).weight != 0.0) { + minimized_points.push_back(point); + num_points++; + break; } } } + } - LG << "Number of cameras " << num_cameras; - LG << "Number of points " << num_points; + LG << "Number of cameras " << num_cameras; + LG << "Number of points " << num_points; - evaluation->num_cameras = num_cameras; - evaluation->num_points = num_points; + evaluation->num_cameras = num_cameras; + evaluation->num_points = num_points; - if (evaluation->evaluate_jacobian) { // Evaluate jacobian matrix. - ceres::CRSMatrix evaluated_jacobian; - ceres::Problem::EvaluateOptions eval_options; + if (evaluation->evaluate_jacobian) { // Evaluate jacobian matrix. + ceres::CRSMatrix evaluated_jacobian; + ceres::Problem::EvaluateOptions eval_options; - // Cameras goes first in the ordering. - int max_image = tracks.MaxImage(); - for (int i = 0; i <= max_image; i++) { - const EuclideanCamera *camera = reconstruction->CameraForImage(i); - if (camera) { - double *current_camera_R_t = &(*all_cameras_R_t)[i](0); + // Cameras goes first in the ordering. + int max_image = tracks.MaxImage(); + for (int i = 0; i <= max_image; i++) { + const EuclideanCamera *camera = reconstruction->CameraForImage(i); + if (camera) { + double *current_camera_R_t = &(*all_cameras_R_t)[i](0); - // All cameras are variable now. - problem->SetParameterBlockVariable(current_camera_R_t); + // All cameras are variable now. + problem->SetParameterBlockVariable(current_camera_R_t); - eval_options.parameter_blocks.push_back(current_camera_R_t); - } + eval_options.parameter_blocks.push_back(current_camera_R_t); } + } - // Points goes at the end of ordering, - for (int i = 0; i < minimized_points.size(); i++) { - EuclideanPoint *point = minimized_points.at(i); - eval_options.parameter_blocks.push_back(&point->X(0)); - } + // Points goes at the end of ordering, + for (int i = 0; i < minimized_points.size(); i++) { + EuclideanPoint *point = minimized_points.at(i); + eval_options.parameter_blocks.push_back(&point->X(0)); + } - problem->Evaluate(eval_options, - NULL, NULL, NULL, - &evaluated_jacobian); + problem->Evaluate(eval_options, + NULL, NULL, NULL, + &evaluated_jacobian); - CRSMatrixToEigenMatrix(evaluated_jacobian, &evaluation->jacobian); - } + CRSMatrixToEigenMatrix(evaluated_jacobian, &evaluation->jacobian); + } +} + +template<typename CostFunction> +void AddResidualBlockToProblemImpl(const CameraIntrinsics *invariant_intrinsics, + double observed_x, double observed_y, + double weight, + double intrinsics_block[OFFSET_MAX], + double *camera_R_t, + EuclideanPoint *point, + ceres::Problem* problem) { + problem->AddResidualBlock(new ceres::AutoDiffCostFunction< + CostFunction, 2, OFFSET_MAX, 6, 3>( + new CostFunction( + invariant_intrinsics, + observed_x, observed_y, + weight)), + NULL, + intrinsics_block, + camera_R_t, + &point->X(0)); +} + +void AddResidualBlockToProblem(const CameraIntrinsics *invariant_intrinsics, + const Marker &marker, + double marker_weight, + double intrinsics_block[OFFSET_MAX], + double *camera_R_t, + EuclideanPoint *point, + ceres::Problem* problem) { + if (NeedUseInvertIntrinsicsPipeline(invariant_intrinsics)) { + AddResidualBlockToProblemImpl<ReprojectionErrorInvertIntrinsics>( + invariant_intrinsics, + marker.x, marker.y, + marker_weight, + intrinsics_block, + camera_R_t, + point, + problem); + } else { + AddResidualBlockToProblemImpl<ReprojectionErrorApplyIntrinsics>( + invariant_intrinsics, + marker.x, marker.y, + marker_weight, + intrinsics_block, + camera_R_t, + point, + problem); + } } // This is an utility function to only bundle 3D position of @@ -375,10 +601,10 @@ void EuclideanBundlerPerformEvaluation(const Tracks &tracks, // // At this point we only need to bundle points positions, cameras // are to be totally still here. -void EuclideanBundlePointsOnly(const DistortionModelType distortion_model, +void EuclideanBundlePointsOnly(const CameraIntrinsics *invariant_intrinsics, const vector<Marker> &markers, vector<Vec6> &all_cameras_R_t, - double ceres_intrinsics[OFFSET_MAX], + double intrinsics_block[OFFSET_MAX], EuclideanReconstruction *reconstruction) { ceres::Problem::Options problem_options; ceres::Problem problem(problem_options); @@ -392,20 +618,16 @@ void EuclideanBundlePointsOnly(const DistortionModelType distortion_model, } // Rotation of camera denoted in angle axis followed with - // camera translaiton. + // camera translation. double *current_camera_R_t = &all_cameras_R_t[camera->image](0); - problem.AddResidualBlock(new ceres::AutoDiffCostFunction< - OpenCVReprojectionError, 2, OFFSET_MAX, 6, 3>( - new OpenCVReprojectionError( - distortion_model, - marker.x, - marker.y, - 1.0)), - NULL, - ceres_intrinsics, - current_camera_R_t, - &point->X(0)); + AddResidualBlockToProblem(invariant_intrinsics, + marker, + 1.0, + intrinsics_block, + current_camera_R_t, + point, + &problem); problem.SetParameterBlockConstant(current_camera_R_t); num_residuals++; @@ -417,7 +639,7 @@ void EuclideanBundlePointsOnly(const DistortionModelType distortion_model, return; } - problem.SetParameterBlockConstant(ceres_intrinsics); + problem.SetParameterBlockConstant(intrinsics_block); // Configure the solver. ceres::Solver::Options options; @@ -438,7 +660,6 @@ void EuclideanBundlePointsOnly(const DistortionModelType distortion_model, ceres::Solve(options, &problem, &summary); LG << "Final report:\n" << summary.FullReport(); - } } // namespace @@ -464,14 +685,14 @@ void EuclideanBundleCommonIntrinsics( LG << "Original intrinsics: " << *intrinsics; vector<Marker> markers = tracks.AllMarkers(); - // N-th element denotes whether track N is a constant zero-weigthed track. + // N-th element denotes whether track N is a constant zero-weighted track. vector<bool> zero_weight_tracks_flags(tracks.MaxTrack() + 1, true); // Residual blocks with 10 parameters are unwieldly with Ceres, so pack the // intrinsics into a single block and rely on local parameterizations to // control which intrinsics are allowed to vary. - double ceres_intrinsics[OFFSET_MAX]; - PackIntrinisicsIntoArray(*intrinsics, ceres_intrinsics); + double intrinsics_block[OFFSET_MAX]; + PackIntrinisicsIntoArray(*intrinsics, intrinsics_block); // Convert cameras rotations to angle axis and merge with translation // into single parameter block for maximal minimization speed. @@ -509,24 +730,20 @@ void EuclideanBundleCommonIntrinsics( } // Rotation of camera denoted in angle axis followed with - // camera translaiton. + // camera translation. double *current_camera_R_t = &all_cameras_R_t[camera->image](0); // Skip residual block for markers which does have absolutely // no affect on the final solution. // This way ceres is not gonna to go crazy. if (marker.weight != 0.0) { - problem.AddResidualBlock(new ceres::AutoDiffCostFunction< - OpenCVReprojectionError, 2, OFFSET_MAX, 6, 3>( - new OpenCVReprojectionError( - intrinsics->GetDistortionModelType(), - marker.x, - marker.y, - marker.weight)), - NULL, - ceres_intrinsics, - current_camera_R_t, - &point->X(0)); + AddResidualBlockToProblem(intrinsics, + marker, + marker.weight, + intrinsics_block, + current_camera_R_t, + point, + &problem); // We lock the first camera to better deal with scene orientation ambiguity. if (!have_locked_camera) { @@ -561,7 +778,7 @@ void EuclideanBundleCommonIntrinsics( if (bundle_intrinsics == BUNDLE_NO_INTRINSICS) { // No camera intrinsics are being refined, // set the whole parameter block as constant for best performance. - problem.SetParameterBlockConstant(ceres_intrinsics); + problem.SetParameterBlockConstant(intrinsics_block); } else { // Set the camera intrinsics that are not to be bundled as // constant using some macro trickery. @@ -586,7 +803,7 @@ void EuclideanBundleCommonIntrinsics( ceres::SubsetParameterization *subset_parameterization = new ceres::SubsetParameterization(OFFSET_MAX, constant_intrinsics); - problem.SetParameterization(ceres_intrinsics, subset_parameterization); + problem.SetParameterization(intrinsics_block, subset_parameterization); } // Configure the solver. @@ -616,7 +833,7 @@ void EuclideanBundleCommonIntrinsics( // Copy intrinsics back. if (bundle_intrinsics != BUNDLE_NO_INTRINSICS) - UnpackIntrinsicsFromArray(ceres_intrinsics, intrinsics); + UnpackIntrinsicsFromArray(intrinsics_block, intrinsics); LG << "Final intrinsics: " << *intrinsics; @@ -641,10 +858,10 @@ void EuclideanBundleCommonIntrinsics( if (zero_weight_markers.size()) { LG << "Refining position of constant zero-weighted tracks"; - EuclideanBundlePointsOnly(intrinsics->GetDistortionModelType(), + EuclideanBundlePointsOnly(intrinsics, zero_weight_markers, all_cameras_R_t, - ceres_intrinsics, + intrinsics_block, reconstruction); } } diff --git a/intern/libmv/libmv/simple_pipeline/camera_intrinsics.cc b/intern/libmv/libmv/simple_pipeline/camera_intrinsics.cc index 5e4e07b3c4c..a95b394ad06 100644 --- a/intern/libmv/libmv/simple_pipeline/camera_intrinsics.cc +++ b/intern/libmv/libmv/simple_pipeline/camera_intrinsics.cc @@ -131,6 +131,8 @@ void CameraIntrinsics::ResetLookupGrids() { undistort_.Reset(); } +// Polynomial model. + PolynomialCameraIntrinsics::PolynomialCameraIntrinsics() : CameraIntrinsics() { SetRadialDistortion(0.0, 0.0, 0.0); @@ -193,6 +195,8 @@ void PolynomialCameraIntrinsics::InvertIntrinsics( normalized_y); } +// Division model. + DivisionCameraIntrinsics::DivisionCameraIntrinsics() : CameraIntrinsics() { SetDistortion(0.0, 0.0); @@ -241,6 +245,57 @@ void DivisionCameraIntrinsics::InvertIntrinsics(double image_x, normalized_y); } +// Nuke model. + +NukeCameraIntrinsics::NukeCameraIntrinsics() + : CameraIntrinsics() { + SetDistortion(0.0, 0.0); +} + +NukeCameraIntrinsics::NukeCameraIntrinsics( + const NukeCameraIntrinsics &from) + : CameraIntrinsics(from) { + SetDistortion(from.k1(), from.k1()); +} + +void NukeCameraIntrinsics::SetDistortion(double k1, double k2) { + parameters_[OFFSET_K1] = k1; + parameters_[OFFSET_K2] = k2; + ResetLookupGrids(); +} + +void NukeCameraIntrinsics::ApplyIntrinsics(double normalized_x, + double normalized_y, + double *image_x, + double *image_y) const { + ApplyNukeDistortionModel(focal_length_x(), + focal_length_y(), + principal_point_x(), + principal_point_y(), + image_width(), image_height(), + k1(), k2(), + normalized_x, + normalized_y, + image_x, + image_y); +} + +void NukeCameraIntrinsics::InvertIntrinsics(double image_x, + double image_y, + double *normalized_x, + double *normalized_y) const { + InvertNukeDistortionModel(focal_length_x(), + focal_length_y(), + principal_point_x(), + principal_point_y(), + image_width(), image_height(), + k1(), k2(), + image_x, + image_y, + normalized_x, + normalized_y); +} + std::ostream& operator <<(std::ostream &os, const CameraIntrinsics &intrinsics) { if (intrinsics.focal_length_x() == intrinsics.focal_length_x()) { @@ -281,6 +336,14 @@ std::ostream& operator <<(std::ostream &os, PRINT_NONZERO_COEFFICIENT(division_intrinsics, k2); break; } + case DISTORTION_MODEL_NUKE: + { + const NukeCameraIntrinsics *nuke_intrinsics = + static_cast<const NukeCameraIntrinsics *>(&intrinsics); + PRINT_NONZERO_COEFFICIENT(nuke_intrinsics, k1); + PRINT_NONZERO_COEFFICIENT(nuke_intrinsics, k2); + break; + } default: LOG(FATAL) << "Unknown distortion model."; } diff --git a/intern/libmv/libmv/simple_pipeline/camera_intrinsics.h b/intern/libmv/libmv/simple_pipeline/camera_intrinsics.h index 6a3ade81089..782fd56c54c 100644 --- a/intern/libmv/libmv/simple_pipeline/camera_intrinsics.h +++ b/intern/libmv/libmv/simple_pipeline/camera_intrinsics.h @@ -276,7 +276,7 @@ class CameraIntrinsics { class PolynomialCameraIntrinsics : public CameraIntrinsics { public: // This constants defines an offset of corresponding coefficients - // in the arameters_ array. + // in the parameters_ array. enum { OFFSET_K1, OFFSET_K2, @@ -342,7 +342,7 @@ class PolynomialCameraIntrinsics : public CameraIntrinsics { class DivisionCameraIntrinsics : public CameraIntrinsics { public: // This constants defines an offset of corresponding coefficients - // in the arameters_ array. + // in the parameters_ array. enum { OFFSET_K1, OFFSET_K2, @@ -393,6 +393,60 @@ class DivisionCameraIntrinsics : public CameraIntrinsics { double parameters_[NUM_PARAMETERS]; }; +class NukeCameraIntrinsics : public CameraIntrinsics { + public: + // This constants defines an offset of corresponding coefficients + // in the parameters_ array. + enum { + OFFSET_K1, + OFFSET_K2, + + // This defines the size of array which we need to have in order + // to store all the coefficients. + NUM_PARAMETERS, + }; + + NukeCameraIntrinsics(); + NukeCameraIntrinsics(const NukeCameraIntrinsics &from); + + DistortionModelType GetDistortionModelType() const { + return DISTORTION_MODEL_NUKE; + } + + int num_distortion_parameters() const { return NUM_PARAMETERS; } + double *distortion_parameters() { return parameters_; }; + const double *distortion_parameters() const { return parameters_; }; + + double k1() const { return parameters_[OFFSET_K1]; } + double k2() const { return parameters_[OFFSET_K2]; } + + // Set radial distortion coeffcients. + void SetDistortion(double k1, double k2); + + // Apply camera intrinsics to the normalized point to get image coordinates. + // + // This applies the lens distortion to a point which is in normalized + // camera coordinates (i.e. the principal point is at (0, 0)) to get image + // coordinates in pixels. + void ApplyIntrinsics(double normalized_x, + double normalized_y, + double *image_x, + double *image_y) const; + + // Invert camera intrinsics on the image point to get normalized coordinates. + // + // This reverses the effect of lens distortion on a point which is in image + // coordinates to get normalized camera coordinates. + void InvertIntrinsics(double image_x, + double image_y, + double *normalized_x, + double *normalized_y) const; + + private: + // Double-parameter division distortion model. + double parameters_[NUM_PARAMETERS]; +}; + /// A human-readable representation of the camera intrinsic parameters. std::ostream& operator <<(std::ostream &os, const CameraIntrinsics &intrinsics); diff --git a/intern/libmv/libmv/simple_pipeline/distortion_models.cc b/intern/libmv/libmv/simple_pipeline/distortion_models.cc index 9b6dca2678a..c069fc6f623 100644 --- a/intern/libmv/libmv/simple_pipeline/distortion_models.cc +++ b/intern/libmv/libmv/simple_pipeline/distortion_models.cc @@ -194,4 +194,96 @@ void InvertDivisionDistortionModel(const double focal_length_x, *normalized_y = normalized(1); } +struct ApplyNukeIntrinsicsCostFunction { + public: + typedef Vec2 FMatrixType; + typedef Vec2 XMatrixType; + + ApplyNukeIntrinsicsCostFunction(const double focal_length_x, + const double focal_length_y, + const double principal_point_x, + const double principal_point_y, + const int image_width, + const int image_height, + const double k1, + const double k2, + const double expected_normalized_x, + const double expected_normalized_y) + : focal_length_x_(focal_length_x), + focal_length_y_(focal_length_y), + principal_point_x_(principal_point_x), + principal_point_y_(principal_point_y), + image_width_(image_width), + image_height_(image_height), + k1_(k1), k2_(k2), + expected_normalized_x_(expected_normalized_x), + expected_normalized_y_(expected_normalized_y) {} + + Vec2 operator()(const Vec2 &image_coordinate) const { + double actual_normalized_x, actual_normalized_y; + + InvertNukeDistortionModel(focal_length_x_, + focal_length_y_, + principal_point_x_, + principal_point_y_, + image_width_, image_height_, + k1_, k2_, + image_coordinate(0), image_coordinate(1), + &actual_normalized_x, &actual_normalized_y); + + Vec2 fx; + fx << (actual_normalized_x - expected_normalized_x_), + (actual_normalized_y - expected_normalized_y_); + return fx; + } + double focal_length_x_; + double focal_length_y_; + double principal_point_x_; + double principal_point_y_; + int image_width_; + int image_height_; + double k1_, k2_; + double expected_normalized_x_, expected_normalized_y_; +}; + +void ApplyNukeDistortionModel(const double focal_length_x, + const double focal_length_y, + const double principal_point_x, + const double principal_point_y, + const int image_width, + const int image_height, + const double k1, + const double k2, + const double normalized_x, + const double normalized_y, + double *image_x, + double *image_y) { + // Compute the initial guess. For a camera with no distortion, this will also + // be the final answer; the LM iteration will terminate immediately. + Vec2 image; + image(0) = normalized_x * focal_length_x + principal_point_x; + image(1) = normalized_y * focal_length_y + principal_point_y; + + // TODO(sergey): Use Ceres minimizer instead. + typedef LevenbergMarquardt<ApplyNukeIntrinsicsCostFunction> Solver; + + ApplyNukeIntrinsicsCostFunction intrinsics_cost(focal_length_x, + focal_length_y, + principal_point_x, + principal_point_y, + image_width, + image_height, + k1, k2, + normalized_x, normalized_y); + Solver::SolverParameters params; + Solver solver(intrinsics_cost); + + /*Solver::Results results =*/ solver.minimize(params, &image); + + // TODO(keir): Better error handling. + + *image_x = image(0); + *image_y = image(1); +} + } // namespace libmv diff --git a/intern/libmv/libmv/simple_pipeline/distortion_models.h b/intern/libmv/libmv/simple_pipeline/distortion_models.h index 4f8e2295a0e..6ba351d729d 100644 --- a/intern/libmv/libmv/simple_pipeline/distortion_models.h +++ b/intern/libmv/libmv/simple_pipeline/distortion_models.h @@ -21,11 +21,14 @@ #ifndef LIBMV_SIMPLE_PIPELINE_DISTORTION_MODELS_H_ #define LIBMV_SIMPLE_PIPELINE_DISTORTION_MODELS_H_ +#include <algorithm> + namespace libmv { enum DistortionModelType { DISTORTION_MODEL_POLYNOMIAL, - DISTORTION_MODEL_DIVISION + DISTORTION_MODEL_DIVISION, + DISTORTION_MODEL_NUKE, }; // Invert camera intrinsics on the image point to get normalized coordinates. @@ -126,6 +129,79 @@ inline void ApplyDivisionDistortionModel(const T &focal_length_x, *image_y = focal_length_y * yd + principal_point_y; } +// Invert camera intrinsics on the image point to get normalized coordinates. +// This inverts the radial lens distortion to a point which is in image pixel +// coordinates to get normalized coordinates. +// +// Uses Nuke distortion model. +template <typename T> +void InvertNukeDistortionModel(const T &focal_length_x, + const T &focal_length_y, + const T &principal_point_x, + const T &principal_point_y, + const int image_width, + const int image_height, + const T &k1, + const T &k2, + const T &image_x, + const T &image_y, + T *normalized_x, + T *normalized_y) { + // According to the documentation: + // + // xu = xd / (1 + k0 * rd^2 + k1 * rd^4) + // yu = yd / (1 + k0 * rd^2 + k1 * rd^4) + // + // Legend: + // (xd, yd) are the distorted cartesian coordinates, + // (rd, phid) are the distorted polar coordinates, + // (xu, yu) are the undistorted cartesian coordinates, + // (ru, phiu) are the undistorted polar coordinates, + // the k-values are the distortion coefficients. + // + // The coordinate systems are relative to the distortion centre. + + const int max_image_size = std::max(image_width, image_height); + const double max_half_image_size = max_image_size * 0.5; + + if (max_half_image_size == 0.0) { + *normalized_x = image_x * max_half_image_size / focal_length_x; + *normalized_y = image_y * max_half_image_size / focal_length_y; + return; + } + + const T xd = (image_x - principal_point_x) / max_half_image_size; + const T yd = (image_y - principal_point_y) / max_half_image_size; + + T rd2 = xd*xd + yd*yd; + T rd4 = rd2 * rd2; + T r_coeff = T(1) / (T(1) + k1*rd2 + k2*rd4); + T xu = xd * r_coeff; + T yu = yd * r_coeff; + + *normalized_x = xu * max_half_image_size / focal_length_x; + *normalized_y = yu * max_half_image_size / focal_length_y; +} + +// Apply camera intrinsics to the normalized point to get image coordinates. +// This applies the radial lens distortion to a point which is in normalized +// camera coordinates (i.e. the principal point is at (0, 0)) to get image +// coordinates in pixels. Templated for use with autodifferentiation. +// +// Uses Nuke distortion model. +void ApplyNukeDistortionModel(const double focal_length_x, + const double focal_length_y, + const double principal_point_x, + const double principal_point_y, + const int image_width, + const int image_height, + const double k1, + const double k2, + const double normalized_x, + const double normalized_y, + double *image_x, + double *image_y); + } // namespace libmv #endif // LIBMV_SIMPLE_PIPELINE_DISTORTION_MODELS_H_ diff --git a/intern/mantaflow/intern/MANTA_main.cpp b/intern/mantaflow/intern/MANTA_main.cpp index d6c1d05e0da..58d49622597 100644 --- a/intern/mantaflow/intern/MANTA_main.cpp +++ b/intern/mantaflow/intern/MANTA_main.cpp @@ -48,7 +48,16 @@ #include "MEM_guardedalloc.h" -std::atomic<int> MANTA::solverID(0); +using std::cerr; +using std::cout; +using std::endl; +using std::ifstream; +using std::istringstream; +using std::ofstream; +using std::ostringstream; +using std::to_string; + +atomic<int> MANTA::solverID(0); int MANTA::with_debug(0); /* Number of particles that the cache reads at once (with zlib). */ @@ -61,29 +70,30 @@ int MANTA::with_debug(0); MANTA::MANTA(int *res, FluidModifierData *mmd) : mCurrentID(++solverID) { if (with_debug) - std::cout << "FLUID: " << mCurrentID << " with res(" << res[0] << ", " << res[1] << ", " - << res[2] << ")" << std::endl; - - mmd->domain->fluid = this; - - mUsingLiquid = (mmd->domain->type == FLUID_DOMAIN_TYPE_LIQUID); - mUsingSmoke = (mmd->domain->type == FLUID_DOMAIN_TYPE_GAS); - mUsingNoise = (mmd->domain->flags & FLUID_DOMAIN_USE_NOISE) && mUsingSmoke; - mUsingFractions = (mmd->domain->flags & FLUID_DOMAIN_USE_FRACTIONS) && mUsingLiquid; - mUsingMesh = (mmd->domain->flags & FLUID_DOMAIN_USE_MESH) && mUsingLiquid; - mUsingMVel = (mmd->domain->flags & FLUID_DOMAIN_USE_SPEED_VECTORS) && mUsingLiquid; - mUsingGuiding = (mmd->domain->flags & FLUID_DOMAIN_USE_GUIDE); - mUsingDrops = (mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY) && mUsingLiquid; - mUsingBubbles = (mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_BUBBLE) && mUsingLiquid; - mUsingFloats = (mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_FOAM) && mUsingLiquid; - mUsingTracers = (mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_TRACER) && mUsingLiquid; - - mUsingHeat = (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_HEAT) && mUsingSmoke; - mUsingFire = (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_FIRE) && mUsingSmoke; - mUsingColors = (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_COLORS) && mUsingSmoke; - mUsingObstacle = (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE); - mUsingInvel = (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_INVEL); - mUsingOutflow = (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW); + cout << "FLUID: " << mCurrentID << " with res(" << res[0] << ", " << res[1] << ", " << res[2] + << ")" << endl; + + FluidDomainSettings *mds = mmd->domain; + mds->fluid = this; + + mUsingLiquid = (mds->type == FLUID_DOMAIN_TYPE_LIQUID); + mUsingSmoke = (mds->type == FLUID_DOMAIN_TYPE_GAS); + mUsingNoise = (mds->flags & FLUID_DOMAIN_USE_NOISE) && mUsingSmoke; + mUsingFractions = (mds->flags & FLUID_DOMAIN_USE_FRACTIONS) && mUsingLiquid; + mUsingMesh = (mds->flags & FLUID_DOMAIN_USE_MESH) && mUsingLiquid; + mUsingMVel = (mds->flags & FLUID_DOMAIN_USE_SPEED_VECTORS) && mUsingLiquid; + mUsingGuiding = (mds->flags & FLUID_DOMAIN_USE_GUIDE); + mUsingDrops = (mds->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY) && mUsingLiquid; + mUsingBubbles = (mds->particle_type & FLUID_DOMAIN_PARTICLE_BUBBLE) && mUsingLiquid; + mUsingFloats = (mds->particle_type & FLUID_DOMAIN_PARTICLE_FOAM) && mUsingLiquid; + mUsingTracers = (mds->particle_type & FLUID_DOMAIN_PARTICLE_TRACER) && mUsingLiquid; + + mUsingHeat = (mds->active_fields & FLUID_DOMAIN_ACTIVE_HEAT) && mUsingSmoke; + mUsingFire = (mds->active_fields & FLUID_DOMAIN_ACTIVE_FIRE) && mUsingSmoke; + mUsingColors = (mds->active_fields & FLUID_DOMAIN_ACTIVE_COLORS) && mUsingSmoke; + mUsingObstacle = (mds->active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE); + mUsingInvel = (mds->active_fields & FLUID_DOMAIN_ACTIVE_INVEL); + mUsingOutflow = (mds->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW); // Simulation constants mTempAmb = 0; // TODO: Maybe use this later for buoyancy calculation @@ -91,10 +101,8 @@ MANTA::MANTA(int *res, FluidModifierData *mmd) : mCurrentID(++solverID) mResY = res[1]; mResZ = res[2]; mMaxRes = MAX3(mResX, mResY, mResZ); - mConstantScaling = 64.0f / mMaxRes; - mConstantScaling = (mConstantScaling < 1.0f) ? 1.0f : mConstantScaling; mTotalCells = mResX * mResY * mResZ; - mResGuiding = mmd->domain->res; + mResGuiding = mds->res; // Smoke low res grids mDensity = nullptr; @@ -184,86 +192,89 @@ MANTA::MANTA(int *res, FluidModifierData *mmd) : mCurrentID(++solverID) // Setup Mantaflow in Python initializeMantaflow(); + // Initializa RNA map with values that Python will need + initializeRNAMap(mmd); + // Initialize Mantaflow variables in Python // Liquid if (mUsingLiquid) { - initDomain(mmd); - initLiquid(mmd); + initDomain(); + initLiquid(); if (mUsingObstacle) - initObstacle(mmd); + initObstacle(); if (mUsingInvel) - initInVelocity(mmd); + initInVelocity(); if (mUsingOutflow) - initOutflow(mmd); + initOutflow(); if (mUsingDrops || mUsingBubbles || mUsingFloats || mUsingTracers) { - mUpresParticle = mmd->domain->particle_scale; + mUpresParticle = mds->particle_scale; mResXParticle = mUpresParticle * mResX; mResYParticle = mUpresParticle * mResY; mResZParticle = mUpresParticle * mResZ; mTotalCellsParticles = mResXParticle * mResYParticle * mResZParticle; - initSndParts(mmd); - initLiquidSndParts(mmd); + initSndParts(); + initLiquidSndParts(); } if (mUsingMesh) { - mUpresMesh = mmd->domain->mesh_scale; + mUpresMesh = mds->mesh_scale; mResXMesh = mUpresMesh * mResX; mResYMesh = mUpresMesh * mResY; mResZMesh = mUpresMesh * mResZ; mTotalCellsMesh = mResXMesh * mResYMesh * mResZMesh; // Initialize Mantaflow variables in Python - initMesh(mmd); - initLiquidMesh(mmd); + initMesh(); + initLiquidMesh(); } if (mUsingGuiding) { - mResGuiding = (mmd->domain->guide_parent) ? mmd->domain->guide_res : mmd->domain->res; - initGuiding(mmd); + mResGuiding = (mds->guide_parent) ? mds->guide_res : mds->res; + initGuiding(); } if (mUsingFractions) { - initFractions(mmd); + initFractions(); } } // Smoke if (mUsingSmoke) { - initDomain(mmd); - initSmoke(mmd); + initDomain(); + initSmoke(); if (mUsingHeat) - initHeat(mmd); + initHeat(); if (mUsingFire) - initFire(mmd); + initFire(); if (mUsingColors) - initColors(mmd); + initColors(); if (mUsingObstacle) - initObstacle(mmd); + initObstacle(); if (mUsingInvel) - initInVelocity(mmd); + initInVelocity(); if (mUsingOutflow) - initOutflow(mmd); + initOutflow(); if (mUsingGuiding) { - mResGuiding = (mmd->domain->guide_parent) ? mmd->domain->guide_res : mmd->domain->res; - initGuiding(mmd); + mResGuiding = (mds->guide_parent) ? mds->guide_res : mds->res; + initGuiding(); } if (mUsingNoise) { - int amplify = mmd->domain->noise_scale; + int amplify = mds->noise_scale; mResXNoise = amplify * mResX; mResYNoise = amplify * mResY; mResZNoise = amplify * mResZ; mTotalCellsHigh = mResXNoise * mResYNoise * mResZNoise; // Initialize Mantaflow variables in Python - initNoise(mmd); - initSmokeNoise(mmd); + initNoise(); + initSmokeNoise(); if (mUsingFire) - initFireHigh(mmd); + initFireHigh(); if (mUsingColors) - initColorsHigh(mmd); + initColorsHigh(); } } updatePointers(); @@ -272,32 +283,32 @@ MANTA::MANTA(int *res, FluidModifierData *mmd) : mCurrentID(++solverID) void MANTA::initDomain(FluidModifierData *mmd) { // Vector will hold all python commands that are to be executed - std::vector<std::string> pythonCommands; + vector<string> pythonCommands; // Set manta debug level first pythonCommands.push_back(manta_import + manta_debuglevel); - std::ostringstream ss; + ostringstream ss; ss << "set_manta_debuglevel(" << with_debug << ")"; pythonCommands.push_back(ss.str()); // Now init basic fluid domain - std::string tmpString = fluid_variables + fluid_solver + fluid_alloc + fluid_cache_helper + - fluid_bake_multiprocessing + fluid_bake_data + fluid_bake_noise + - fluid_bake_mesh + fluid_bake_particles + fluid_bake_guiding + - fluid_file_import + fluid_file_export + fluid_save_data + - fluid_load_data + fluid_pre_step + fluid_post_step + - fluid_adapt_time_step + fluid_time_stepping; - std::string finalString = parseScript(tmpString, mmd); + string tmpString = fluid_variables + fluid_solver + fluid_alloc + fluid_cache_helper + + fluid_bake_multiprocessing + fluid_bake_data + fluid_bake_noise + + fluid_bake_mesh + fluid_bake_particles + fluid_bake_guiding + + fluid_file_import + fluid_file_export + fluid_save_data + fluid_load_data + + fluid_pre_step + fluid_post_step + fluid_adapt_time_step + + fluid_time_stepping; + string finalString = parseScript(tmpString, mmd); pythonCommands.push_back(finalString); runPythonString(pythonCommands); } void MANTA::initNoise(FluidModifierData *mmd) { - std::vector<std::string> pythonCommands; - std::string tmpString = fluid_variables_noise + fluid_solver_noise; - std::string finalString = parseScript(tmpString, mmd); + vector<string> pythonCommands; + string tmpString = fluid_variables_noise + fluid_solver_noise; + string finalString = parseScript(tmpString, mmd); pythonCommands.push_back(finalString); runPythonString(pythonCommands); @@ -305,10 +316,10 @@ void MANTA::initNoise(FluidModifierData *mmd) void MANTA::initSmoke(FluidModifierData *mmd) { - std::vector<std::string> pythonCommands; - std::string tmpString = smoke_variables + smoke_alloc + smoke_adaptive_step + smoke_save_data + - smoke_load_data + smoke_step; - std::string finalString = parseScript(tmpString, mmd); + vector<string> pythonCommands; + string tmpString = smoke_variables + smoke_alloc + smoke_adaptive_step + smoke_save_data + + smoke_load_data + smoke_step; + string finalString = parseScript(tmpString, mmd); pythonCommands.push_back(finalString); runPythonString(pythonCommands); @@ -316,10 +327,10 @@ void MANTA::initSmoke(FluidModifierData *mmd) void MANTA::initSmokeNoise(FluidModifierData *mmd) { - std::vector<std::string> pythonCommands; - std::string tmpString = smoke_variables_noise + smoke_alloc_noise + smoke_wavelet_noise + - smoke_save_noise + smoke_load_noise + smoke_step_noise; - std::string finalString = parseScript(tmpString, mmd); + vector<string> pythonCommands; + string tmpString = smoke_variables_noise + smoke_alloc_noise + smoke_wavelet_noise + + smoke_save_noise + smoke_load_noise + smoke_step_noise; + string finalString = parseScript(tmpString, mmd); pythonCommands.push_back(finalString); runPythonString(pythonCommands); @@ -329,9 +340,9 @@ void MANTA::initSmokeNoise(FluidModifierData *mmd) void MANTA::initHeat(FluidModifierData *mmd) { if (!mHeat) { - std::vector<std::string> pythonCommands; - std::string tmpString = smoke_alloc_heat + smoke_with_heat; - std::string finalString = parseScript(tmpString, mmd); + vector<string> pythonCommands; + string tmpString = smoke_alloc_heat + smoke_with_heat; + string finalString = parseScript(tmpString, mmd); pythonCommands.push_back(finalString); runPythonString(pythonCommands); @@ -342,9 +353,9 @@ void MANTA::initHeat(FluidModifierData *mmd) void MANTA::initFire(FluidModifierData *mmd) { if (!mFuel) { - std::vector<std::string> pythonCommands; - std::string tmpString = smoke_alloc_fire + smoke_with_fire; - std::string finalString = parseScript(tmpString, mmd); + vector<string> pythonCommands; + string tmpString = smoke_alloc_fire + smoke_with_fire; + string finalString = parseScript(tmpString, mmd); pythonCommands.push_back(finalString); runPythonString(pythonCommands); @@ -355,9 +366,9 @@ void MANTA::initFire(FluidModifierData *mmd) void MANTA::initFireHigh(FluidModifierData *mmd) { if (!mFuelHigh) { - std::vector<std::string> pythonCommands; - std::string tmpString = smoke_alloc_fire_noise + smoke_with_fire; - std::string finalString = parseScript(tmpString, mmd); + vector<string> pythonCommands; + string tmpString = smoke_alloc_fire_noise + smoke_with_fire; + string finalString = parseScript(tmpString, mmd); pythonCommands.push_back(finalString); runPythonString(pythonCommands); @@ -368,9 +379,9 @@ void MANTA::initFireHigh(FluidModifierData *mmd) void MANTA::initColors(FluidModifierData *mmd) { if (!mColorR) { - std::vector<std::string> pythonCommands; - std::string tmpString = smoke_alloc_colors + smoke_init_colors + smoke_with_colors; - std::string finalString = parseScript(tmpString, mmd); + vector<string> pythonCommands; + string tmpString = smoke_alloc_colors + smoke_init_colors + smoke_with_colors; + string finalString = parseScript(tmpString, mmd); pythonCommands.push_back(finalString); runPythonString(pythonCommands); @@ -381,9 +392,9 @@ void MANTA::initColors(FluidModifierData *mmd) void MANTA::initColorsHigh(FluidModifierData *mmd) { if (!mColorRHigh) { - std::vector<std::string> pythonCommands; - std::string tmpString = smoke_alloc_colors_noise + smoke_init_colors_noise + smoke_with_colors; - std::string finalString = parseScript(tmpString, mmd); + vector<string> pythonCommands; + string tmpString = smoke_alloc_colors_noise + smoke_init_colors_noise + smoke_with_colors; + string finalString = parseScript(tmpString, mmd); pythonCommands.push_back(finalString); runPythonString(pythonCommands); @@ -394,10 +405,10 @@ void MANTA::initColorsHigh(FluidModifierData *mmd) void MANTA::initLiquid(FluidModifierData *mmd) { if (!mPhiIn) { - std::vector<std::string> pythonCommands; - std::string tmpString = liquid_variables + liquid_alloc + liquid_init_phi + liquid_save_data + - liquid_load_data + liquid_adaptive_step + liquid_step; - std::string finalString = parseScript(tmpString, mmd); + vector<string> pythonCommands; + string tmpString = liquid_variables + liquid_alloc + liquid_init_phi + liquid_save_data + + liquid_load_data + liquid_adaptive_step + liquid_step; + string finalString = parseScript(tmpString, mmd); pythonCommands.push_back(finalString); runPythonString(pythonCommands); @@ -407,9 +418,9 @@ void MANTA::initLiquid(FluidModifierData *mmd) void MANTA::initMesh(FluidModifierData *mmd) { - std::vector<std::string> pythonCommands; - std::string tmpString = fluid_variables_mesh + fluid_solver_mesh + liquid_load_mesh; - std::string finalString = parseScript(tmpString, mmd); + vector<string> pythonCommands; + string tmpString = fluid_variables_mesh + fluid_solver_mesh + liquid_load_mesh; + string finalString = parseScript(tmpString, mmd); pythonCommands.push_back(finalString); runPythonString(pythonCommands); @@ -418,9 +429,9 @@ void MANTA::initMesh(FluidModifierData *mmd) void MANTA::initLiquidMesh(FluidModifierData *mmd) { - std::vector<std::string> pythonCommands; - std::string tmpString = liquid_alloc_mesh + liquid_step_mesh + liquid_save_mesh; - std::string finalString = parseScript(tmpString, mmd); + vector<string> pythonCommands; + string tmpString = liquid_alloc_mesh + liquid_step_mesh + liquid_save_mesh; + string finalString = parseScript(tmpString, mmd); pythonCommands.push_back(finalString); runPythonString(pythonCommands); @@ -430,9 +441,9 @@ void MANTA::initLiquidMesh(FluidModifierData *mmd) void MANTA::initObstacle(FluidModifierData *mmd) { if (!mPhiObsIn) { - std::vector<std::string> pythonCommands; - std::string tmpString = fluid_alloc_obstacle + fluid_with_obstacle; - std::string finalString = parseScript(tmpString, mmd); + vector<string> pythonCommands; + string tmpString = fluid_alloc_obstacle + fluid_with_obstacle; + string finalString = parseScript(tmpString, mmd); pythonCommands.push_back(finalString); runPythonString(pythonCommands); @@ -443,10 +454,10 @@ void MANTA::initObstacle(FluidModifierData *mmd) void MANTA::initGuiding(FluidModifierData *mmd) { if (!mPhiGuideIn) { - std::vector<std::string> pythonCommands; - std::string tmpString = fluid_variables_guiding + fluid_solver_guiding + fluid_alloc_guiding + - fluid_save_guiding + fluid_load_vel + fluid_load_guiding; - std::string finalString = parseScript(tmpString, mmd); + vector<string> pythonCommands; + string tmpString = fluid_variables_guiding + fluid_solver_guiding + fluid_alloc_guiding + + fluid_save_guiding + fluid_load_vel + fluid_load_guiding; + string finalString = parseScript(tmpString, mmd); pythonCommands.push_back(finalString); runPythonString(pythonCommands); @@ -456,9 +467,9 @@ void MANTA::initGuiding(FluidModifierData *mmd) void MANTA::initFractions(FluidModifierData *mmd) { - std::vector<std::string> pythonCommands; - std::string tmpString = fluid_alloc_fractions + fluid_with_fractions; - std::string finalString = parseScript(tmpString, mmd); + vector<string> pythonCommands; + string tmpString = fluid_alloc_fractions + fluid_with_fractions; + string finalString = parseScript(tmpString, mmd); pythonCommands.push_back(finalString); runPythonString(pythonCommands); @@ -468,9 +479,9 @@ void MANTA::initFractions(FluidModifierData *mmd) void MANTA::initInVelocity(FluidModifierData *mmd) { if (!mInVelocityX) { - std::vector<std::string> pythonCommands; - std::string tmpString = fluid_alloc_invel + fluid_with_invel; - std::string finalString = parseScript(tmpString, mmd); + vector<string> pythonCommands; + string tmpString = fluid_alloc_invel + fluid_with_invel; + string finalString = parseScript(tmpString, mmd); pythonCommands.push_back(finalString); runPythonString(pythonCommands); @@ -481,9 +492,9 @@ void MANTA::initInVelocity(FluidModifierData *mmd) void MANTA::initOutflow(FluidModifierData *mmd) { if (!mPhiOutIn) { - std::vector<std::string> pythonCommands; - std::string tmpString = fluid_alloc_outflow + fluid_with_outflow; - std::string finalString = parseScript(tmpString, mmd); + vector<string> pythonCommands; + string tmpString = fluid_alloc_outflow + fluid_with_outflow; + string finalString = parseScript(tmpString, mmd); pythonCommands.push_back(finalString); runPythonString(pythonCommands); @@ -493,9 +504,9 @@ void MANTA::initOutflow(FluidModifierData *mmd) void MANTA::initSndParts(FluidModifierData *mmd) { - std::vector<std::string> pythonCommands; - std::string tmpString = fluid_variables_particles + fluid_solver_particles; - std::string finalString = parseScript(tmpString, mmd); + vector<string> pythonCommands; + string tmpString = fluid_variables_particles + fluid_solver_particles; + string finalString = parseScript(tmpString, mmd); pythonCommands.push_back(finalString); runPythonString(pythonCommands); @@ -504,11 +515,11 @@ void MANTA::initSndParts(FluidModifierData *mmd) void MANTA::initLiquidSndParts(FluidModifierData *mmd) { if (!mSndParticleData) { - std::vector<std::string> pythonCommands; - std::string tmpString = liquid_alloc_particles + liquid_variables_particles + - liquid_step_particles + fluid_with_sndparts + liquid_load_particles + - liquid_save_particles; - std::string finalString = parseScript(tmpString, mmd); + vector<string> pythonCommands; + string tmpString = liquid_alloc_particles + liquid_variables_particles + + liquid_step_particles + fluid_with_sndparts + liquid_load_particles + + liquid_save_particles; + string finalString = parseScript(tmpString, mmd); pythonCommands.push_back(finalString); runPythonString(pythonCommands); @@ -518,19 +529,22 @@ void MANTA::initLiquidSndParts(FluidModifierData *mmd) MANTA::~MANTA() { if (with_debug) - std::cout << "~FLUID: " << mCurrentID << " with res(" << mResX << ", " << mResY << ", " - << mResZ << ")" << std::endl; + cout << "~FLUID: " << mCurrentID << " with res(" << mResX << ", " << mResY << ", " << mResZ + << ")" << endl; // Destruction string for Python - std::string tmpString = ""; - std::vector<std::string> pythonCommands; + string tmpString = ""; + vector<string> pythonCommands; bool result = false; tmpString += manta_import; tmpString += fluid_delete_all; + // Initializa RNA map with values that Python will need + initializeRNAMap(); + // Leave out mmd argument in parseScript since only looking up IDs - std::string finalString = parseScript(tmpString); + string finalString = parseScript(tmpString); pythonCommands.push_back(finalString); result = runPythonString(pythonCommands); @@ -538,12 +552,12 @@ MANTA::~MANTA() (void)result; // not needed in release } -bool MANTA::runPythonString(std::vector<std::string> commands) +bool MANTA::runPythonString(vector<string> commands) { int success = -1; PyGILState_STATE gilstate = PyGILState_Ensure(); - for (std::vector<std::string>::iterator it = commands.begin(); it != commands.end(); ++it) { - std::string command = *it; + for (vector<string>::iterator it = commands.begin(); it != commands.end(); ++it) { + string command = *it; #ifdef WIN32 // special treatment for windows when running python code @@ -568,10 +582,10 @@ bool MANTA::runPythonString(std::vector<std::string> commands) void MANTA::initializeMantaflow() { if (with_debug) - std::cout << "Fluid: Initializing Mantaflow framework" << std::endl; + cout << "Fluid: Initializing Mantaflow framework" << endl; - std::string filename = "manta_scene_" + std::to_string(mCurrentID) + ".py"; - std::vector<std::string> fill = std::vector<std::string>(); + string filename = "manta_scene_" + to_string(mCurrentID) + ".py"; + vector<string> fill = vector<string>(); // Initialize extension classes and wrappers srand(0); @@ -583,17 +597,17 @@ void MANTA::initializeMantaflow() void MANTA::terminateMantaflow() { if (with_debug) - std::cout << "Fluid: Releasing Mantaflow framework" << std::endl; + cout << "Fluid: Releasing Mantaflow framework" << endl; PyGILState_STATE gilstate = PyGILState_Ensure(); Pb::finalize(); // Namespace from Mantaflow (registry) PyGILState_Release(gilstate); } -static std::string getCacheFileEnding(char cache_format) +static string getCacheFileEnding(char cache_format) { if (MANTA::with_debug) - std::cout << "MANTA::getCacheFileEnding()" << std::endl; + cout << "MANTA::getCacheFileEnding()" << endl; switch (cache_format) { case FLUID_DOMAIN_FILE_UNI: @@ -607,409 +621,237 @@ static std::string getCacheFileEnding(char cache_format) case FLUID_DOMAIN_FILE_OBJECT: return FLUID_DOMAIN_EXTENSION_OBJ; default: - std::cerr << "Fluid Error -- Could not find file extension. Using default file extension." - << std::endl; + cerr << "Fluid Error -- Could not find file extension. Using default file extension." + << endl; return FLUID_DOMAIN_EXTENSION_UNI; } } -std::string MANTA::getRealValue(const std::string &varName, FluidModifierData *mmd) +static string getBooleanString(int value) { - std::ostringstream ss; - bool is2D = false; - int tmpVar; - float tmpFloat; + return (value) ? "True" : "False"; +} - if (varName == "ID") { - ss << mCurrentID; - return ss.str(); - } +void MANTA::initializeRNAMap(FluidModifierData *mmd) +{ + if (with_debug) + cout << "MANTA::initializeRNAMap()" << endl; + + mRNAMap["ID"] = to_string(mCurrentID); if (!mmd) { - std::cerr << "Fluid Error -- Invalid modifier data." << std::endl; - ss << "ERROR - INVALID MODIFIER DATA"; - return ss.str(); - } - - is2D = (mmd->domain->solver_res == 2); - - if (varName == "USING_SMOKE") - ss << ((mmd->domain->type == FLUID_DOMAIN_TYPE_GAS) ? "True" : "False"); - else if (varName == "USING_LIQUID") - ss << ((mmd->domain->type == FLUID_DOMAIN_TYPE_LIQUID) ? "True" : "False"); - else if (varName == "USING_COLORS") - ss << (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_COLORS ? "True" : "False"); - else if (varName == "USING_HEAT") - ss << (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_HEAT ? "True" : "False"); - else if (varName == "USING_FIRE") - ss << (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_FIRE ? "True" : "False"); - else if (varName == "USING_NOISE") - ss << (mmd->domain->flags & FLUID_DOMAIN_USE_NOISE ? "True" : "False"); - else if (varName == "USING_OBSTACLE") - ss << (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE ? "True" : "False"); - else if (varName == "USING_GUIDING") - ss << (mmd->domain->flags & FLUID_DOMAIN_USE_GUIDE ? "True" : "False"); - else if (varName == "USING_INVEL") - ss << (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_INVEL ? "True" : "False"); - else if (varName == "USING_OUTFLOW") - ss << (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW ? "True" : "False"); - else if (varName == "USING_LOG_DISSOLVE") - ss << (mmd->domain->flags & FLUID_DOMAIN_USE_DISSOLVE_LOG ? "True" : "False"); - else if (varName == "USING_DISSOLVE") - ss << (mmd->domain->flags & FLUID_DOMAIN_USE_DISSOLVE ? "True" : "False"); - else if (varName == "SOLVER_DIM") - ss << mmd->domain->solver_res; - else if (varName == "DO_OPEN") { - tmpVar = (FLUID_DOMAIN_BORDER_BACK | FLUID_DOMAIN_BORDER_FRONT | FLUID_DOMAIN_BORDER_LEFT | - FLUID_DOMAIN_BORDER_RIGHT | FLUID_DOMAIN_BORDER_BOTTOM | FLUID_DOMAIN_BORDER_TOP); - ss << (((mmd->domain->border_collisions & tmpVar) == tmpVar) ? "False" : "True"); - } - else if (varName == "BOUND_CONDITIONS") { - if (mmd->domain->solver_res == 2) { - if ((mmd->domain->border_collisions & FLUID_DOMAIN_BORDER_LEFT) == 0) - ss << "x"; - if ((mmd->domain->border_collisions & FLUID_DOMAIN_BORDER_RIGHT) == 0) - ss << "X"; - if ((mmd->domain->border_collisions & FLUID_DOMAIN_BORDER_FRONT) == 0) - ss << "y"; - if ((mmd->domain->border_collisions & FLUID_DOMAIN_BORDER_BACK) == 0) - ss << "Y"; - } - if (mmd->domain->solver_res == 3) { - if ((mmd->domain->border_collisions & FLUID_DOMAIN_BORDER_LEFT) == 0) - ss << "x"; - if ((mmd->domain->border_collisions & FLUID_DOMAIN_BORDER_RIGHT) == 0) - ss << "X"; - if ((mmd->domain->border_collisions & FLUID_DOMAIN_BORDER_FRONT) == 0) - ss << "y"; - if ((mmd->domain->border_collisions & FLUID_DOMAIN_BORDER_BACK) == 0) - ss << "Y"; - if ((mmd->domain->border_collisions & FLUID_DOMAIN_BORDER_BOTTOM) == 0) - ss << "z"; - if ((mmd->domain->border_collisions & FLUID_DOMAIN_BORDER_TOP) == 0) - ss << "Z"; - } - } - else if (varName == "BOUNDARY_WIDTH") - ss << mmd->domain->boundary_width; - else if (varName == "RES") - ss << mMaxRes; - else if (varName == "RESX") - ss << mResX; - else if (varName == "RESY") - if (is2D) { - ss << mResZ; - } - else { - ss << mResY; - } - else if (varName == "RESZ") { - if (is2D) { - ss << 1; - } - else { - ss << mResZ; - } - } - else if (varName == "FRAME_LENGTH") - ss << mmd->domain->frame_length; - else if (varName == "CFL") - ss << mmd->domain->cfl_condition; - else if (varName == "DT") - ss << mmd->domain->dt; - else if (varName == "TIMESTEPS_MIN") - ss << mmd->domain->timesteps_minimum; - else if (varName == "TIMESTEPS_MAX") - ss << mmd->domain->timesteps_maximum; - else if (varName == "TIME_TOTAL") - ss << mmd->domain->time_total; - else if (varName == "TIME_PER_FRAME") - ss << mmd->domain->time_per_frame; - else if (varName == "VORTICITY") - ss << mmd->domain->vorticity / mConstantScaling; - else if (varName == "FLAME_VORTICITY") - ss << mmd->domain->flame_vorticity / mConstantScaling; - else if (varName == "NOISE_SCALE") - ss << mmd->domain->noise_scale; - else if (varName == "MESH_SCALE") - ss << mmd->domain->mesh_scale; - else if (varName == "PARTICLE_SCALE") - ss << mmd->domain->particle_scale; - else if (varName == "NOISE_RESX") - ss << mResXNoise; - else if (varName == "NOISE_RESY") { - if (is2D) { - ss << mResZNoise; - } - else { - ss << mResYNoise; - } - } - else if (varName == "NOISE_RESZ") { - if (is2D) { - ss << 1; - } - else { - ss << mResZNoise; - } - } - else if (varName == "MESH_RESX") - ss << mResXMesh; - else if (varName == "MESH_RESY") { - if (is2D) { - ss << mResZMesh; - } - else { - ss << mResYMesh; - } - } - else if (varName == "MESH_RESZ") { - if (is2D) { - ss << 1; - } - else { - ss << mResZMesh; - } - } - else if (varName == "PARTICLE_RESX") - ss << mResXParticle; - else if (varName == "PARTICLE_RESY") { - if (is2D) { - ss << mResZParticle; - } - else { - ss << mResYParticle; - } - } - else if (varName == "PARTICLE_RESZ") { - if (is2D) { - ss << 1; - } - else { - ss << mResZParticle; - } - } - else if (varName == "GUIDING_RESX") - ss << mResGuiding[0]; - else if (varName == "GUIDING_RESY") { - if (is2D) { - ss << mResGuiding[2]; - } - else { - ss << mResGuiding[1]; - } + if (with_debug) + cout << "No modifier data given in RNA map setup - returning early" << endl; + return; } - else if (varName == "GUIDING_RESZ") { - if (is2D) { - ss << 1; - } - else { - ss << mResGuiding[2]; - } + + FluidDomainSettings *mds = mmd->domain; + bool is2D = (mds->solver_res == 2); + + string borderCollisions = ""; + if ((mds->border_collisions & FLUID_DOMAIN_BORDER_LEFT) == 0) + borderCollisions += "x"; + if ((mds->border_collisions & FLUID_DOMAIN_BORDER_RIGHT) == 0) + borderCollisions += "X"; + if ((mds->border_collisions & FLUID_DOMAIN_BORDER_FRONT) == 0) + borderCollisions += "y"; + if ((mds->border_collisions & FLUID_DOMAIN_BORDER_BACK) == 0) + borderCollisions += "Y"; + if ((mds->border_collisions & FLUID_DOMAIN_BORDER_BOTTOM) == 0) + borderCollisions += "z"; + if ((mds->border_collisions & FLUID_DOMAIN_BORDER_TOP) == 0) + borderCollisions += "Z"; + + string simulationMethod = ""; + if (mds->simulation_method & FLUID_DOMAIN_METHOD_FLIP) + simulationMethod += "'FLIP'"; + else if (mds->simulation_method & FLUID_DOMAIN_METHOD_APIC) + simulationMethod += "'APIC'"; + + string particleTypesStr = ""; + if (mds->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY) + particleTypesStr += "PtypeSpray"; + if (mds->particle_type & FLUID_DOMAIN_PARTICLE_BUBBLE) { + if (!particleTypesStr.empty()) + particleTypesStr += "|"; + particleTypesStr += "PtypeBubble"; + } + if (mds->particle_type & FLUID_DOMAIN_PARTICLE_FOAM) { + if (!particleTypesStr.empty()) + particleTypesStr += "|"; + particleTypesStr += "PtypeFoam"; + } + if (mds->particle_type & FLUID_DOMAIN_PARTICLE_TRACER) { + if (!particleTypesStr.empty()) + particleTypesStr += "|"; + particleTypesStr += "PtypeTracer"; + } + if (particleTypesStr.empty()) + particleTypesStr = "0"; + + int particleTypes = (FLUID_DOMAIN_PARTICLE_SPRAY | FLUID_DOMAIN_PARTICLE_BUBBLE | + FLUID_DOMAIN_PARTICLE_FOAM | FLUID_DOMAIN_PARTICLE_TRACER); + + string cacheDirectory(mds->cache_directory); + + float viscosity = mds->viscosity_base * pow(10.0f, -mds->viscosity_exponent); + float domainSize = MAX3(mds->global_size[0], mds->global_size[1], mds->global_size[2]); + + mRNAMap["USING_SMOKE"] = getBooleanString(mds->type == FLUID_DOMAIN_TYPE_GAS); + mRNAMap["USING_LIQUID"] = getBooleanString(mds->type == FLUID_DOMAIN_TYPE_LIQUID); + mRNAMap["USING_COLORS"] = getBooleanString(mds->active_fields & FLUID_DOMAIN_ACTIVE_COLORS); + mRNAMap["USING_HEAT"] = getBooleanString(mds->active_fields & FLUID_DOMAIN_ACTIVE_HEAT); + mRNAMap["USING_FIRE"] = getBooleanString(mds->active_fields & FLUID_DOMAIN_ACTIVE_FIRE); + mRNAMap["USING_NOISE"] = getBooleanString(mds->flags & FLUID_DOMAIN_USE_NOISE); + mRNAMap["USING_OBSTACLE"] = getBooleanString(mds->active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE); + mRNAMap["USING_GUIDING"] = getBooleanString(mds->flags & FLUID_DOMAIN_USE_GUIDE); + mRNAMap["USING_INVEL"] = getBooleanString(mds->active_fields & FLUID_DOMAIN_ACTIVE_INVEL); + mRNAMap["USING_OUTFLOW"] = getBooleanString(mds->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW); + mRNAMap["USING_LOG_DISSOLVE"] = getBooleanString(mds->flags & FLUID_DOMAIN_USE_DISSOLVE_LOG); + mRNAMap["USING_DISSOLVE"] = getBooleanString(mds->flags & FLUID_DOMAIN_USE_DISSOLVE); + mRNAMap["DO_OPEN"] = getBooleanString(mds->border_collisions == 0); + mRNAMap["CACHE_RESUMABLE"] = getBooleanString(mds->cache_type != FLUID_DOMAIN_CACHE_FINAL); + mRNAMap["USING_ADAPTIVETIME"] = getBooleanString(mds->flags & FLUID_DOMAIN_USE_ADAPTIVE_TIME); + mRNAMap["USING_SPEEDVECTORS"] = getBooleanString(mds->flags & FLUID_DOMAIN_USE_SPEED_VECTORS); + mRNAMap["USING_FRACTIONS"] = getBooleanString(mds->flags & FLUID_DOMAIN_USE_FRACTIONS); + mRNAMap["DELETE_IN_OBSTACLE"] = getBooleanString(mds->flags & FLUID_DOMAIN_DELETE_IN_OBSTACLE); + mRNAMap["USING_DIFFUSION"] = getBooleanString(mds->flags & FLUID_DOMAIN_USE_DIFFUSION); + mRNAMap["USING_MESH"] = getBooleanString(mds->flags & FLUID_DOMAIN_USE_MESH); + mRNAMap["USING_IMPROVED_MESH"] = getBooleanString(mds->mesh_generator == + FLUID_DOMAIN_MESH_IMPROVED); + mRNAMap["USING_SNDPARTS"] = getBooleanString(mds->particle_type & particleTypes); + mRNAMap["SNDPARTICLE_BOUNDARY_DELETE"] = getBooleanString(mds->sndparticle_boundary == + SNDPARTICLE_BOUNDARY_DELETE); + mRNAMap["SNDPARTICLE_BOUNDARY_PUSHOUT"] = getBooleanString(mds->sndparticle_boundary == + SNDPARTICLE_BOUNDARY_PUSHOUT); + + mRNAMap["SOLVER_DIM"] = to_string(mds->solver_res); + mRNAMap["BOUND_CONDITIONS"] = borderCollisions; + mRNAMap["BOUNDARY_WIDTH"] = to_string(mds->boundary_width); + mRNAMap["RES"] = to_string(mMaxRes); + mRNAMap["RESX"] = to_string(mResX); + mRNAMap["RESY"] = (is2D) ? to_string(mResZ) : to_string(mResY); + mRNAMap["RESZ"] = (is2D) ? to_string(1) : to_string(mResZ); + mRNAMap["TIME_SCALE"] = to_string(mds->time_scale); + mRNAMap["FRAME_LENGTH"] = to_string(mds->frame_length); + mRNAMap["CFL"] = to_string(mds->cfl_condition); + mRNAMap["DT"] = to_string(mds->dt); + mRNAMap["TIMESTEPS_MIN"] = to_string(mds->timesteps_minimum); + mRNAMap["TIMESTEPS_MAX"] = to_string(mds->timesteps_maximum); + mRNAMap["TIME_TOTAL"] = to_string(mds->time_total); + mRNAMap["TIME_PER_FRAME"] = to_string(mds->time_per_frame); + mRNAMap["VORTICITY"] = to_string(mds->vorticity); + mRNAMap["FLAME_VORTICITY"] = to_string(mds->flame_vorticity); + mRNAMap["NOISE_SCALE"] = to_string(mds->noise_scale); + mRNAMap["MESH_SCALE"] = to_string(mds->mesh_scale); + mRNAMap["PARTICLE_SCALE"] = to_string(mds->particle_scale); + mRNAMap["NOISE_RESX"] = to_string(mResXNoise); + mRNAMap["NOISE_RESY"] = (is2D) ? to_string(mResZNoise) : to_string(mResYNoise); + mRNAMap["NOISE_RESZ"] = (is2D) ? to_string(1) : to_string(mResZNoise); + mRNAMap["MESH_RESX"] = to_string(mResXMesh); + mRNAMap["MESH_RESY"] = (is2D) ? to_string(mResZMesh) : to_string(mResYMesh); + mRNAMap["MESH_RESZ"] = (is2D) ? to_string(1) : to_string(mResZMesh); + mRNAMap["PARTICLE_RESX"] = to_string(mResXParticle); + mRNAMap["PARTICLE_RESY"] = (is2D) ? to_string(mResZParticle) : to_string(mResYParticle); + mRNAMap["PARTICLE_RESZ"] = (is2D) ? to_string(1) : to_string(mResZParticle); + mRNAMap["GUIDING_RESX"] = to_string(mResGuiding[0]); + mRNAMap["GUIDING_RESY"] = (is2D) ? to_string(mResGuiding[2]) : to_string(mResGuiding[1]); + mRNAMap["GUIDING_RESZ"] = (is2D) ? to_string(1) : to_string(mResGuiding[2]); + mRNAMap["MIN_RESX"] = to_string(mds->res_min[0]); + mRNAMap["MIN_RESY"] = to_string(mds->res_min[1]); + mRNAMap["MIN_RESZ"] = to_string(mds->res_min[2]); + mRNAMap["BASE_RESX"] = to_string(mds->base_res[0]); + mRNAMap["BASE_RESY"] = to_string(mds->base_res[1]); + mRNAMap["BASE_RESZ"] = to_string(mds->base_res[2]); + mRNAMap["WLT_STR"] = to_string(mds->noise_strength); + mRNAMap["NOISE_POSSCALE"] = to_string(mds->noise_pos_scale); + mRNAMap["NOISE_TIMEANIM"] = to_string(mds->noise_time_anim); + mRNAMap["COLOR_R"] = to_string(mds->active_color[0]); + mRNAMap["COLOR_G"] = to_string(mds->active_color[1]); + mRNAMap["COLOR_B"] = to_string(mds->active_color[2]); + mRNAMap["BUOYANCY_ALPHA"] = to_string(mds->alpha); + mRNAMap["BUOYANCY_BETA"] = to_string(mds->beta); + mRNAMap["DISSOLVE_SPEED"] = to_string(mds->diss_speed); + mRNAMap["BURNING_RATE"] = to_string(mds->burning_rate); + mRNAMap["FLAME_SMOKE"] = to_string(mds->flame_smoke); + mRNAMap["IGNITION_TEMP"] = to_string(mds->flame_ignition); + mRNAMap["MAX_TEMP"] = to_string(mds->flame_max_temp); + mRNAMap["FLAME_SMOKE_COLOR_X"] = to_string(mds->flame_smoke_color[0]); + mRNAMap["FLAME_SMOKE_COLOR_Y"] = to_string(mds->flame_smoke_color[1]); + mRNAMap["FLAME_SMOKE_COLOR_Z"] = to_string(mds->flame_smoke_color[2]); + mRNAMap["CURRENT_FRAME"] = to_string(mmd->time); + mRNAMap["START_FRAME"] = to_string(mds->cache_frame_start); + mRNAMap["END_FRAME"] = to_string(mds->cache_frame_end); + mRNAMap["CACHE_DATA_FORMAT"] = to_string(mds->cache_data_format); + mRNAMap["CACHE_MESH_FORMAT"] = to_string(mds->cache_mesh_format); + mRNAMap["CACHE_NOISE_FORMAT"] = to_string(mds->cache_noise_format); + mRNAMap["CACHE_PARTICLE_FORMAT"] = to_string(mds->cache_particle_format); + mRNAMap["SIMULATION_METHOD"] = simulationMethod; + mRNAMap["FLIP_RATIO"] = to_string(mds->flip_ratio); + mRNAMap["PARTICLE_RANDOMNESS"] = to_string(mds->particle_randomness); + mRNAMap["PARTICLE_NUMBER"] = to_string(mds->particle_number); + mRNAMap["PARTICLE_MINIMUM"] = to_string(mds->particle_minimum); + mRNAMap["PARTICLE_MAXIMUM"] = to_string(mds->particle_maximum); + mRNAMap["PARTICLE_RADIUS"] = to_string(mds->particle_radius); + mRNAMap["FRACTIONS_THRESHOLD"] = to_string(mds->fractions_threshold); + mRNAMap["MESH_CONCAVE_UPPER"] = to_string(mds->mesh_concave_upper); + mRNAMap["MESH_CONCAVE_LOWER"] = to_string(mds->mesh_concave_lower); + mRNAMap["MESH_PARTICLE_RADIUS"] = to_string(mds->mesh_particle_radius); + mRNAMap["MESH_SMOOTHEN_POS"] = to_string(mds->mesh_smoothen_pos); + mRNAMap["MESH_SMOOTHEN_NEG"] = to_string(mds->mesh_smoothen_neg); + mRNAMap["PARTICLE_BAND_WIDTH"] = to_string(mds->particle_band_width); + mRNAMap["SNDPARTICLE_TAU_MIN_WC"] = to_string(mds->sndparticle_tau_min_wc); + mRNAMap["SNDPARTICLE_TAU_MAX_WC"] = to_string(mds->sndparticle_tau_max_wc); + mRNAMap["SNDPARTICLE_TAU_MIN_TA"] = to_string(mds->sndparticle_tau_min_ta); + mRNAMap["SNDPARTICLE_TAU_MAX_TA"] = to_string(mds->sndparticle_tau_max_ta); + mRNAMap["SNDPARTICLE_TAU_MIN_K"] = to_string(mds->sndparticle_tau_min_k); + mRNAMap["SNDPARTICLE_TAU_MAX_K"] = to_string(mds->sndparticle_tau_max_k); + mRNAMap["SNDPARTICLE_K_WC"] = to_string(mds->sndparticle_k_wc); + mRNAMap["SNDPARTICLE_K_TA"] = to_string(mds->sndparticle_k_ta); + mRNAMap["SNDPARTICLE_K_B"] = to_string(mds->sndparticle_k_b); + mRNAMap["SNDPARTICLE_K_D"] = to_string(mds->sndparticle_k_d); + mRNAMap["SNDPARTICLE_L_MIN"] = to_string(mds->sndparticle_l_min); + mRNAMap["SNDPARTICLE_L_MAX"] = to_string(mds->sndparticle_l_max); + mRNAMap["SNDPARTICLE_POTENTIAL_RADIUS"] = to_string(mds->sndparticle_potential_radius); + mRNAMap["SNDPARTICLE_UPDATE_RADIUS"] = to_string(mds->sndparticle_update_radius); + mRNAMap["LIQUID_SURFACE_TENSION"] = to_string(mds->surface_tension); + mRNAMap["FLUID_VISCOSITY"] = to_string(viscosity); + mRNAMap["FLUID_DOMAIN_SIZE"] = to_string(domainSize); + mRNAMap["SNDPARTICLE_TYPES"] = particleTypesStr; + mRNAMap["GUIDING_ALPHA"] = to_string(mds->guide_alpha); + mRNAMap["GUIDING_BETA"] = to_string(mds->guide_beta); + mRNAMap["GUIDING_FACTOR"] = to_string(mds->guide_vel_factor); + mRNAMap["GRAVITY_X"] = to_string(mds->gravity[0]); + mRNAMap["GRAVITY_Y"] = to_string(mds->gravity[1]); + mRNAMap["GRAVITY_Z"] = to_string(mds->gravity[2]); + mRNAMap["CACHE_DIR"] = cacheDirectory; +} + +string MANTA::getRealValue(const string &varName) +{ + if (with_debug) + cout << "MANTA::getRealValue()" << endl; + + unordered_map<string, string>::iterator it; + it = mRNAMap.find(varName); + + if (it == mRNAMap.end()) { + cerr << "Fluid Error -- variable " << varName << " not found in RNA map " << it->second + << endl; + return ""; } - else if (varName == "MIN_RESX") - ss << mmd->domain->res_min[0]; - else if (varName == "MIN_RESY") - ss << mmd->domain->res_min[1]; - else if (varName == "MIN_RESZ") - ss << mmd->domain->res_min[2]; - else if (varName == "BASE_RESX") - ss << mmd->domain->base_res[0]; - else if (varName == "BASE_RESY") - ss << mmd->domain->base_res[1]; - else if (varName == "BASE_RESZ") - ss << mmd->domain->base_res[2]; - else if (varName == "WLT_STR") - ss << mmd->domain->noise_strength; - else if (varName == "NOISE_POSSCALE") - ss << mmd->domain->noise_pos_scale; - else if (varName == "NOISE_TIMEANIM") - ss << mmd->domain->noise_time_anim; - else if (varName == "COLOR_R") - ss << mmd->domain->active_color[0]; - else if (varName == "COLOR_G") - ss << mmd->domain->active_color[1]; - else if (varName == "COLOR_B") - ss << mmd->domain->active_color[2]; - else if (varName == "BUOYANCY_ALPHA") - ss << mmd->domain->alpha; - else if (varName == "BUOYANCY_BETA") - ss << mmd->domain->beta; - else if (varName == "DISSOLVE_SPEED") - ss << mmd->domain->diss_speed; - else if (varName == "BURNING_RATE") - ss << mmd->domain->burning_rate; - else if (varName == "FLAME_SMOKE") - ss << mmd->domain->flame_smoke; - else if (varName == "IGNITION_TEMP") - ss << mmd->domain->flame_ignition; - else if (varName == "MAX_TEMP") - ss << mmd->domain->flame_max_temp; - else if (varName == "FLAME_SMOKE_COLOR_X") - ss << mmd->domain->flame_smoke_color[0]; - else if (varName == "FLAME_SMOKE_COLOR_Y") - ss << mmd->domain->flame_smoke_color[1]; - else if (varName == "FLAME_SMOKE_COLOR_Z") - ss << mmd->domain->flame_smoke_color[2]; - else if (varName == "CURRENT_FRAME") - ss << mmd->time; - else if (varName == "START_FRAME") - ss << mmd->domain->cache_frame_start; - else if (varName == "END_FRAME") - ss << mmd->domain->cache_frame_end; - else if (varName == "CACHE_DATA_FORMAT") - ss << getCacheFileEnding(mmd->domain->cache_data_format); - else if (varName == "CACHE_MESH_FORMAT") - ss << getCacheFileEnding(mmd->domain->cache_mesh_format); - else if (varName == "CACHE_NOISE_FORMAT") - ss << getCacheFileEnding(mmd->domain->cache_noise_format); - else if (varName == "CACHE_PARTICLE_FORMAT") - ss << getCacheFileEnding(mmd->domain->cache_particle_format); - else if (varName == "SIMULATION_METHOD") { - if (mmd->domain->simulation_method & FLUID_DOMAIN_METHOD_FLIP) { - ss << "'FLIP'"; - } - else if (mmd->domain->simulation_method & FLUID_DOMAIN_METHOD_APIC) { - ss << "'APIC'"; - } - else { - ss << "'NONE'"; - } + if (with_debug) { + cout << "Found variable " << varName << " with value " << it->second << endl; } - else if (varName == "FLIP_RATIO") - ss << mmd->domain->flip_ratio; - else if (varName == "PARTICLE_RANDOMNESS") - ss << mmd->domain->particle_randomness; - else if (varName == "PARTICLE_NUMBER") - ss << mmd->domain->particle_number; - else if (varName == "PARTICLE_MINIMUM") - ss << mmd->domain->particle_minimum; - else if (varName == "PARTICLE_MAXIMUM") - ss << mmd->domain->particle_maximum; - else if (varName == "PARTICLE_RADIUS") - ss << mmd->domain->particle_radius; - else if (varName == "FRACTIONS_THRESHOLD") - ss << mmd->domain->fractions_threshold; - else if (varName == "MESH_CONCAVE_UPPER") - ss << mmd->domain->mesh_concave_upper; - else if (varName == "MESH_CONCAVE_LOWER") - ss << mmd->domain->mesh_concave_lower; - else if (varName == "MESH_PARTICLE_RADIUS") - ss << mmd->domain->mesh_particle_radius; - else if (varName == "MESH_SMOOTHEN_POS") - ss << mmd->domain->mesh_smoothen_pos; - else if (varName == "MESH_SMOOTHEN_NEG") - ss << mmd->domain->mesh_smoothen_neg; - else if (varName == "USING_MESH") - ss << (mmd->domain->flags & FLUID_DOMAIN_USE_MESH ? "True" : "False"); - else if (varName == "USING_IMPROVED_MESH") - ss << (mmd->domain->mesh_generator == FLUID_DOMAIN_MESH_IMPROVED ? "True" : "False"); - else if (varName == "PARTICLE_BAND_WIDTH") - ss << mmd->domain->particle_band_width; - else if (varName == "SNDPARTICLE_TAU_MIN_WC") - ss << mmd->domain->sndparticle_tau_min_wc; - else if (varName == "SNDPARTICLE_TAU_MAX_WC") - ss << mmd->domain->sndparticle_tau_max_wc; - else if (varName == "SNDPARTICLE_TAU_MIN_TA") - ss << mmd->domain->sndparticle_tau_min_ta; - else if (varName == "SNDPARTICLE_TAU_MAX_TA") - ss << mmd->domain->sndparticle_tau_max_ta; - else if (varName == "SNDPARTICLE_TAU_MIN_K") - ss << mmd->domain->sndparticle_tau_min_k; - else if (varName == "SNDPARTICLE_TAU_MAX_K") - ss << mmd->domain->sndparticle_tau_max_k; - else if (varName == "SNDPARTICLE_K_WC") - ss << mmd->domain->sndparticle_k_wc; - else if (varName == "SNDPARTICLE_K_TA") - ss << mmd->domain->sndparticle_k_ta; - else if (varName == "SNDPARTICLE_K_B") - ss << mmd->domain->sndparticle_k_b; - else if (varName == "SNDPARTICLE_K_D") - ss << mmd->domain->sndparticle_k_d; - else if (varName == "SNDPARTICLE_L_MIN") - ss << mmd->domain->sndparticle_l_min; - else if (varName == "SNDPARTICLE_L_MAX") - ss << mmd->domain->sndparticle_l_max; - else if (varName == "SNDPARTICLE_BOUNDARY_DELETE") - ss << (mmd->domain->sndparticle_boundary == SNDPARTICLE_BOUNDARY_DELETE); - else if (varName == "SNDPARTICLE_BOUNDARY_PUSHOUT") - ss << (mmd->domain->sndparticle_boundary == SNDPARTICLE_BOUNDARY_PUSHOUT); - else if (varName == "SNDPARTICLE_POTENTIAL_RADIUS") - ss << mmd->domain->sndparticle_potential_radius; - else if (varName == "SNDPARTICLE_UPDATE_RADIUS") - ss << mmd->domain->sndparticle_update_radius; - else if (varName == "LIQUID_SURFACE_TENSION") - ss << mmd->domain->surface_tension; - else if (varName == "FLUID_VISCOSITY") - ss << mmd->domain->viscosity_base * pow(10.0f, -mmd->domain->viscosity_exponent); - else if (varName == "FLUID_DOMAIN_SIZE") { - tmpFloat = MAX3( - mmd->domain->global_size[0], mmd->domain->global_size[1], mmd->domain->global_size[2]); - ss << tmpFloat; - } - else if (varName == "SNDPARTICLE_TYPES") { - if (mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY) { - ss << "PtypeSpray"; - } - if (mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_BUBBLE) { - if (!ss.str().empty()) - ss << "|"; - ss << "PtypeBubble"; - } - if (mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_FOAM) { - if (!ss.str().empty()) - ss << "|"; - ss << "PtypeFoam"; - } - if (mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_TRACER) { - if (!ss.str().empty()) - ss << "|"; - ss << "PtypeTracer"; - } - if (ss.str().empty()) - ss << "0"; - } - else if (varName == "USING_SNDPARTS") { - tmpVar = (FLUID_DOMAIN_PARTICLE_SPRAY | FLUID_DOMAIN_PARTICLE_BUBBLE | - FLUID_DOMAIN_PARTICLE_FOAM | FLUID_DOMAIN_PARTICLE_TRACER); - ss << (((mmd->domain->particle_type & tmpVar)) ? "True" : "False"); - } - else if (varName == "GUIDING_ALPHA") - ss << mmd->domain->guide_alpha; - else if (varName == "GUIDING_BETA") - ss << mmd->domain->guide_beta; - else if (varName == "GUIDING_FACTOR") - ss << mmd->domain->guide_vel_factor; - else if (varName == "GRAVITY_X") - ss << mmd->domain->gravity[0]; - else if (varName == "GRAVITY_Y") - ss << mmd->domain->gravity[1]; - else if (varName == "GRAVITY_Z") - ss << mmd->domain->gravity[2]; - else if (varName == "CACHE_DIR") - ss << mmd->domain->cache_directory; - else if (varName == "CACHE_RESUMABLE") - ss << (mmd->domain->cache_type == FLUID_DOMAIN_CACHE_FINAL ? "False" : "True"); - else if (varName == "USING_ADAPTIVETIME") - ss << (mmd->domain->flags & FLUID_DOMAIN_USE_ADAPTIVE_TIME ? "True" : "False"); - else if (varName == "USING_SPEEDVECTORS") - ss << (mmd->domain->flags & FLUID_DOMAIN_USE_SPEED_VECTORS ? "True" : "False"); - else if (varName == "USING_FRACTIONS") - ss << (mmd->domain->flags & FLUID_DOMAIN_USE_FRACTIONS ? "True" : "False"); - else if (varName == "DELETE_IN_OBSTACLE") - ss << (mmd->domain->flags & FLUID_DOMAIN_DELETE_IN_OBSTACLE ? "True" : "False"); - else if (varName == "USING_DIFFUSION") - ss << (mmd->domain->flags & FLUID_DOMAIN_USE_DIFFUSION ? "True" : "False"); - else - std::cerr << "Fluid Error -- Unknown option: " << varName << std::endl; - return ss.str(); -} - -std::string MANTA::parseLine(const std::string &line, FluidModifierData *mmd) + + return it->second; +} + +string MANTA::parseLine(const string &line) { if (line.size() == 0) return ""; - std::string res = ""; + string res = ""; int currPos = 0, start_del = 0, end_del = -1; bool readingVar = false; const char delimiter = '$'; @@ -1022,7 +864,7 @@ std::string MANTA::parseLine(const std::string &line, FluidModifierData *mmd) else if (line[currPos] == delimiter && readingVar) { readingVar = false; end_del = currPos; - res += getRealValue(line.substr(start_del, currPos - start_del), mmd); + res += getRealValue(line.substr(start_del, currPos - start_del)); } currPos++; } @@ -1030,13 +872,21 @@ std::string MANTA::parseLine(const std::string &line, FluidModifierData *mmd) return res; } -std::string MANTA::parseScript(const std::string &setup_string, FluidModifierData *mmd) +string MANTA::parseScript(const string &setup_string, FluidModifierData *mmd) { - std::istringstream f(setup_string); - std::ostringstream res; - std::string line = ""; + if (MANTA::with_debug) + cout << "MANTA::parseScript()" << endl; + + istringstream f(setup_string); + ostringstream res; + string line = ""; + + // Update RNA map if modifier data is handed over + if (mmd) { + initializeRNAMap(mmd); + } while (getline(f, line)) { - res << parseLine(line, mmd) << "\n"; + res << parseLine(line) << "\n"; } return res.str(); } @@ -1044,13 +894,14 @@ std::string MANTA::parseScript(const std::string &setup_string, FluidModifierDat bool MANTA::updateFlipStructures(FluidModifierData *mmd, int framenr) { if (MANTA::with_debug) - std::cout << "MANTA::updateFlipStructures()" << std::endl; + cout << "MANTA::updateFlipStructures()" << endl; + FluidDomainSettings *mds = mmd->domain; mFlipFromFile = false; if (!mUsingLiquid) return false; - if (BLI_path_is_rel(mmd->domain->cache_directory)) + if (BLI_path_is_rel(mds->cache_directory)) return false; int result = 0; @@ -1063,8 +914,8 @@ bool MANTA::updateFlipStructures(FluidModifierData *mmd, int framenr) mFlipParticleData->clear(); mFlipParticleVelocity->clear(); - std::string pformat = getCacheFileEnding(mmd->domain->cache_particle_format); - std::string file = getFile( + string pformat = getCacheFileEnding(mds->cache_particle_format); + string file = getFile( mmd, FLUID_DOMAIN_DIR_DATA, FLUID_DOMAIN_FILE_PP, pformat.c_str(), framenr); expected += 1; @@ -1086,13 +937,14 @@ bool MANTA::updateFlipStructures(FluidModifierData *mmd, int framenr) bool MANTA::updateMeshStructures(FluidModifierData *mmd, int framenr) { if (MANTA::with_debug) - std::cout << "MANTA::updateMeshStructures()" << std::endl; + cout << "MANTA::updateMeshStructures()" << endl; + FluidDomainSettings *mds = mmd->domain; mMeshFromFile = false; if (!mUsingMesh) return false; - if (BLI_path_is_rel(mmd->domain->cache_directory)) + if (BLI_path_is_rel(mds->cache_directory)) return false; int result = 0; @@ -1108,9 +960,9 @@ bool MANTA::updateMeshStructures(FluidModifierData *mmd, int framenr) if (mMeshVelocities) mMeshVelocities->clear(); - std::string mformat = getCacheFileEnding(mmd->domain->cache_mesh_format); - std::string dformat = getCacheFileEnding(mmd->domain->cache_data_format); - std::string file = getFile(mmd, FLUID_DOMAIN_DIR_MESH, FLUID_DOMAIN_FILE_MESH, mformat, framenr); + string mformat = getCacheFileEnding(mds->cache_mesh_format); + string dformat = getCacheFileEnding(mds->cache_data_format); + string file = getFile(mmd, FLUID_DOMAIN_DIR_MESH, FLUID_DOMAIN_FILE_MESH, mformat, framenr); expected += 1; if (BLI_exists(file.c_str())) { @@ -1133,13 +985,14 @@ bool MANTA::updateMeshStructures(FluidModifierData *mmd, int framenr) bool MANTA::updateParticleStructures(FluidModifierData *mmd, int framenr) { if (MANTA::with_debug) - std::cout << "MANTA::updateParticleStructures()" << std::endl; + cout << "MANTA::updateParticleStructures()" << endl; + FluidDomainSettings *mds = mmd->domain; mParticlesFromFile = false; if (!mUsingDrops && !mUsingBubbles && !mUsingFloats && !mUsingTracers) return false; - if (BLI_path_is_rel(mmd->domain->cache_directory)) + if (BLI_path_is_rel(mds->cache_directory)) return false; int result = 0; @@ -1153,8 +1006,8 @@ bool MANTA::updateParticleStructures(FluidModifierData *mmd, int framenr) mSndParticleVelocity->clear(); mSndParticleLife->clear(); - std::string pformat = getCacheFileEnding(mmd->domain->cache_particle_format); - std::string file = getFile( + string pformat = getCacheFileEnding(mds->cache_particle_format); + string file = getFile( mmd, FLUID_DOMAIN_DIR_PARTICLES, FLUID_DOMAIN_FILE_PPSND, pformat, framenr); expected += 1; @@ -1183,21 +1036,21 @@ bool MANTA::updateParticleStructures(FluidModifierData *mmd, int framenr) bool MANTA::updateSmokeStructures(FluidModifierData *mmd, int framenr) { if (MANTA::with_debug) - std::cout << "MANTA::updateGridStructures()" << std::endl; + cout << "MANTA::updateGridStructures()" << endl; + FluidDomainSettings *mds = mmd->domain; mSmokeFromFile = false; if (!mUsingSmoke) return false; - if (BLI_path_is_rel(mmd->domain->cache_directory)) + if (BLI_path_is_rel(mds->cache_directory)) return false; int result = 0; int expected = 0; /* Expected number of read successes for this frame. */ - std::string dformat = getCacheFileEnding(mmd->domain->cache_data_format); - std::string file = getFile( - mmd, FLUID_DOMAIN_DIR_DATA, FLUID_DOMAIN_FILE_DENSITY, dformat, framenr); + string dformat = getCacheFileEnding(mds->cache_data_format); + string file = getFile(mmd, FLUID_DOMAIN_DIR_DATA, FLUID_DOMAIN_FILE_DENSITY, dformat, framenr); expected += 1; if (BLI_exists(file.c_str())) { @@ -1273,21 +1126,22 @@ bool MANTA::updateSmokeStructures(FluidModifierData *mmd, int framenr) bool MANTA::updateNoiseStructures(FluidModifierData *mmd, int framenr) { if (MANTA::with_debug) - std::cout << "MANTA::updateNoiseStructures()" << std::endl; + cout << "MANTA::updateNoiseStructures()" << endl; + FluidDomainSettings *mds = mmd->domain; mNoiseFromFile = false; if (!mUsingSmoke || !mUsingNoise) return false; - if (BLI_path_is_rel(mmd->domain->cache_directory)) + if (BLI_path_is_rel(mds->cache_directory)) return false; int result = 0; int expected = 0; /* Expected number of read successes for this frame. */ - std::string dformat = getCacheFileEnding(mmd->domain->cache_data_format); - std::string nformat = getCacheFileEnding(mmd->domain->cache_noise_format); - std::string file = getFile( + string dformat = getCacheFileEnding(mds->cache_data_format); + string nformat = getCacheFileEnding(mds->cache_noise_format); + string file = getFile( mmd, FLUID_DOMAIN_DIR_NOISE, FLUID_DOMAIN_FILE_DENSITYNOISE, nformat, framenr); expected += 1; @@ -1353,10 +1207,10 @@ bool MANTA::updateNoiseStructures(FluidModifierData *mmd, int framenr) } /* Dirty hack: Needed to format paths from python code that is run via PyRun_SimpleString */ -static std::string escapeSlashes(std::string const &s) +static string escapeSlashes(string const &s) { - std::string result = ""; - for (std::string::const_iterator i = s.begin(), end = s.end(); i != end; ++i) { + string result = ""; + for (string::const_iterator i = s.begin(), end = s.end(); i != end; ++i) { unsigned char c = *i; if (c == '\\') result += "\\\\"; @@ -1369,21 +1223,20 @@ static std::string escapeSlashes(std::string const &s) bool MANTA::writeConfiguration(FluidModifierData *mmd, int framenr) { if (with_debug) - std::cout << "MANTA::writeConfiguration()" << std::endl; + cout << "MANTA::writeConfiguration()" << endl; FluidDomainSettings *mds = mmd->domain; - std::string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_CONFIG); - std::string format = FLUID_DOMAIN_EXTENSION_UNI; - std::string file = getFile( - mmd, FLUID_DOMAIN_DIR_CONFIG, FLUID_DOMAIN_FILE_CONFIG, format, framenr); + string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_CONFIG); + string format = FLUID_DOMAIN_EXTENSION_UNI; + string file = getFile(mmd, FLUID_DOMAIN_DIR_CONFIG, FLUID_DOMAIN_FILE_CONFIG, format, framenr); /* Create 'config' subdir if it does not exist already. */ BLI_dir_create_recursive(directory.c_str()); gzFile gzf = (gzFile)BLI_gzopen(file.c_str(), "wb1"); // do some compression if (!gzf) { - std::cerr << "Fluid Error -- Cannot open file " << file << std::endl; + cerr << "Fluid Error -- Cannot open file " << file << endl; return false; } @@ -1408,17 +1261,18 @@ bool MANTA::writeConfiguration(FluidModifierData *mmd, int framenr) bool MANTA::writeData(FluidModifierData *mmd, int framenr) { if (with_debug) - std::cout << "MANTA::writeData()" << std::endl; + cout << "MANTA::writeData()" << endl; - std::ostringstream ss; - std::vector<std::string> pythonCommands; + ostringstream ss; + vector<string> pythonCommands; + FluidDomainSettings *mds = mmd->domain; - std::string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_DATA); - std::string dformat = getCacheFileEnding(mmd->domain->cache_data_format); - std::string pformat = getCacheFileEnding(mmd->domain->cache_particle_format); + string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_DATA); + string dformat = getCacheFileEnding(mds->cache_data_format); + string pformat = getCacheFileEnding(mds->cache_particle_format); - bool final_cache = (mmd->domain->cache_type == FLUID_DOMAIN_CACHE_FINAL); - std::string resumable_cache = (final_cache) ? "False" : "True"; + bool final_cache = (mds->cache_type == FLUID_DOMAIN_CACHE_FINAL); + string resumable_cache = (final_cache) ? "False" : "True"; ss.str(""); ss << "fluid_save_data_" << mCurrentID << "('" << escapeSlashes(directory) << "', " << framenr @@ -1443,16 +1297,17 @@ bool MANTA::writeData(FluidModifierData *mmd, int framenr) bool MANTA::writeNoise(FluidModifierData *mmd, int framenr) { if (with_debug) - std::cout << "MANTA::writeNoise()" << std::endl; + cout << "MANTA::writeNoise()" << endl; - std::ostringstream ss; - std::vector<std::string> pythonCommands; + ostringstream ss; + vector<string> pythonCommands; + FluidDomainSettings *mds = mmd->domain; - std::string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_NOISE); - std::string nformat = getCacheFileEnding(mmd->domain->cache_noise_format); + string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_NOISE); + string nformat = getCacheFileEnding(mds->cache_noise_format); - bool final_cache = (mmd->domain->cache_type == FLUID_DOMAIN_CACHE_FINAL); - std::string resumable_cache = (final_cache) ? "False" : "True"; + bool final_cache = (mds->cache_type == FLUID_DOMAIN_CACHE_FINAL); + string resumable_cache = (final_cache) ? "False" : "True"; if (mUsingSmoke && mUsingNoise) { ss.str(""); @@ -1466,22 +1321,21 @@ bool MANTA::writeNoise(FluidModifierData *mmd, int framenr) bool MANTA::readConfiguration(FluidModifierData *mmd, int framenr) { if (with_debug) - std::cout << "MANTA::readConfiguration()" << std::endl; + cout << "MANTA::readConfiguration()" << endl; FluidDomainSettings *mds = mmd->domain; float dummy; - std::string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_CONFIG); - std::string format = FLUID_DOMAIN_EXTENSION_UNI; - std::string file = getFile( - mmd, FLUID_DOMAIN_DIR_CONFIG, FLUID_DOMAIN_FILE_CONFIG, format, framenr); + string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_CONFIG); + string format = FLUID_DOMAIN_EXTENSION_UNI; + string file = getFile(mmd, FLUID_DOMAIN_DIR_CONFIG, FLUID_DOMAIN_FILE_CONFIG, format, framenr); if (!hasConfig(mmd, framenr)) return false; gzFile gzf = (gzFile)BLI_gzopen(file.c_str(), "rb"); // do some compression if (!gzf) { - std::cerr << "Fluid Error -- Cannot open file " << file << std::endl; + cerr << "Fluid Error -- Cannot open file " << file << endl; return false; } @@ -1507,21 +1361,22 @@ bool MANTA::readConfiguration(FluidModifierData *mmd, int framenr) bool MANTA::readData(FluidModifierData *mmd, int framenr) { if (with_debug) - std::cout << "MANTA::readData()" << std::endl; + cout << "MANTA::readData()" << endl; if (!mUsingSmoke && !mUsingLiquid) return false; - std::ostringstream ss; - std::vector<std::string> pythonCommands; + ostringstream ss; + vector<string> pythonCommands; + FluidDomainSettings *mds = mmd->domain; bool result = true; - std::string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_DATA); - std::string dformat = getCacheFileEnding(mmd->domain->cache_data_format); - std::string pformat = getCacheFileEnding(mmd->domain->cache_particle_format); + string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_DATA); + string dformat = getCacheFileEnding(mds->cache_data_format); + string pformat = getCacheFileEnding(mds->cache_particle_format); - bool final_cache = (mmd->domain->cache_type == FLUID_DOMAIN_CACHE_FINAL); - std::string resumable_cache = (final_cache) ? "False" : "True"; + bool final_cache = (mds->cache_type == FLUID_DOMAIN_CACHE_FINAL); + string resumable_cache = (final_cache) ? "False" : "True"; /* Sanity check: Are cache files present? */ if (!hasData(mmd, framenr)) @@ -1552,19 +1407,20 @@ bool MANTA::readData(FluidModifierData *mmd, int framenr) bool MANTA::readNoise(FluidModifierData *mmd, int framenr) { if (with_debug) - std::cout << "MANTA::readNoise()" << std::endl; + cout << "MANTA::readNoise()" << endl; if (!mUsingSmoke || !mUsingNoise) return false; - std::ostringstream ss; - std::vector<std::string> pythonCommands; + ostringstream ss; + vector<string> pythonCommands; + FluidDomainSettings *mds = mmd->domain; - std::string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_NOISE); - std::string nformat = getCacheFileEnding(mmd->domain->cache_noise_format); + string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_NOISE); + string nformat = getCacheFileEnding(mds->cache_noise_format); - bool final_cache = (mmd->domain->cache_type == FLUID_DOMAIN_CACHE_FINAL); - std::string resumable_cache = (final_cache) ? "False" : "True"; + bool final_cache = (mds->cache_type == FLUID_DOMAIN_CACHE_FINAL); + string resumable_cache = (final_cache) ? "False" : "True"; /* Sanity check: Are cache files present? */ if (!hasNoise(mmd, framenr)) @@ -1584,17 +1440,18 @@ bool MANTA::readNoise(FluidModifierData *mmd, int framenr) bool MANTA::readMesh(FluidModifierData *mmd, int framenr) { if (with_debug) - std::cout << "MANTA::readMesh()" << std::endl; + cout << "MANTA::readMesh()" << endl; if (!mUsingLiquid || !mUsingMesh) return false; - std::ostringstream ss; - std::vector<std::string> pythonCommands; + ostringstream ss; + vector<string> pythonCommands; + FluidDomainSettings *mds = mmd->domain; - std::string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_MESH); - std::string mformat = getCacheFileEnding(mmd->domain->cache_mesh_format); - std::string dformat = getCacheFileEnding(mmd->domain->cache_data_format); + string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_MESH); + string mformat = getCacheFileEnding(mds->cache_mesh_format); + string dformat = getCacheFileEnding(mds->cache_data_format); /* Sanity check: Are cache files present? */ if (!hasMesh(mmd, framenr)) @@ -1621,21 +1478,22 @@ bool MANTA::readMesh(FluidModifierData *mmd, int framenr) bool MANTA::readParticles(FluidModifierData *mmd, int framenr) { if (with_debug) - std::cout << "MANTA::readParticles()" << std::endl; + cout << "MANTA::readParticles()" << endl; if (!mUsingLiquid) return false; if (!mUsingDrops && !mUsingBubbles && !mUsingFloats && !mUsingTracers) return false; - std::ostringstream ss; - std::vector<std::string> pythonCommands; + ostringstream ss; + vector<string> pythonCommands; + FluidDomainSettings *mds = mmd->domain; - std::string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_PARTICLES); - std::string pformat = getCacheFileEnding(mmd->domain->cache_particle_format); + string directory = getDirectory(mmd, FLUID_DOMAIN_DIR_PARTICLES); + string pformat = getCacheFileEnding(mds->cache_particle_format); - bool final_cache = (mmd->domain->cache_type == FLUID_DOMAIN_CACHE_FINAL); - std::string resumable_cache = (final_cache) ? "False" : "True"; + bool final_cache = (mds->cache_type == FLUID_DOMAIN_CACHE_FINAL); + string resumable_cache = (final_cache) ? "False" : "True"; /* Sanity check: Are cache files present? */ if (!hasParticles(mmd, framenr)) @@ -1652,19 +1510,21 @@ bool MANTA::readParticles(FluidModifierData *mmd, int framenr) bool MANTA::readGuiding(FluidModifierData *mmd, int framenr, bool sourceDomain) { if (with_debug) - std::cout << "MANTA::readGuiding()" << std::endl; + cout << "MANTA::readGuiding()" << endl; + + FluidDomainSettings *mds = mmd->domain; if (!mUsingGuiding) return false; - if (!mmd->domain) + if (!mds) return false; - std::ostringstream ss; - std::vector<std::string> pythonCommands; + ostringstream ss; + vector<string> pythonCommands; - std::string directory = (sourceDomain) ? getDirectory(mmd, FLUID_DOMAIN_DIR_DATA) : - getDirectory(mmd, FLUID_DOMAIN_DIR_GUIDE); - std::string gformat = getCacheFileEnding(mmd->domain->cache_data_format); + string directory = (sourceDomain) ? getDirectory(mmd, FLUID_DOMAIN_DIR_DATA) : + getDirectory(mmd, FLUID_DOMAIN_DIR_GUIDE); + string gformat = getCacheFileEnding(mds->cache_data_format); /* Sanity check: Are cache files present? */ if (!hasGuiding(mmd, framenr, sourceDomain)) @@ -1688,28 +1548,26 @@ bool MANTA::readGuiding(FluidModifierData *mmd, int framenr, bool sourceDomain) bool MANTA::bakeData(FluidModifierData *mmd, int framenr) { if (with_debug) - std::cout << "MANTA::bakeData()" << std::endl; + cout << "MANTA::bakeData()" << endl; - std::string tmpString, finalString; - std::ostringstream ss; - std::vector<std::string> pythonCommands; + string tmpString, finalString; + ostringstream ss; + vector<string> pythonCommands; + FluidDomainSettings *mds = mmd->domain; char cacheDirData[FILE_MAX], cacheDirGuiding[FILE_MAX]; cacheDirData[0] = '\0'; cacheDirGuiding[0] = '\0'; - std::string dformat = getCacheFileEnding(mmd->domain->cache_data_format); - std::string pformat = getCacheFileEnding(mmd->domain->cache_particle_format); - std::string gformat = dformat; // Use same data format for guiding format + string dformat = getCacheFileEnding(mds->cache_data_format); + string pformat = getCacheFileEnding(mds->cache_particle_format); + string gformat = dformat; // Use same data format for guiding format - BLI_path_join(cacheDirData, - sizeof(cacheDirData), - mmd->domain->cache_directory, - FLUID_DOMAIN_DIR_DATA, - nullptr); + BLI_path_join( + cacheDirData, sizeof(cacheDirData), mds->cache_directory, FLUID_DOMAIN_DIR_DATA, nullptr); BLI_path_join(cacheDirGuiding, sizeof(cacheDirGuiding), - mmd->domain->cache_directory, + mds->cache_directory, FLUID_DOMAIN_DIR_GUIDE, nullptr); BLI_path_make_safe(cacheDirData); @@ -1727,31 +1585,26 @@ bool MANTA::bakeData(FluidModifierData *mmd, int framenr) bool MANTA::bakeNoise(FluidModifierData *mmd, int framenr) { if (with_debug) - std::cout << "MANTA::bakeNoise()" << std::endl; + cout << "MANTA::bakeNoise()" << endl; - std::ostringstream ss; - std::vector<std::string> pythonCommands; + ostringstream ss; + vector<string> pythonCommands; + FluidDomainSettings *mds = mmd->domain; char cacheDirData[FILE_MAX], cacheDirNoise[FILE_MAX]; cacheDirData[0] = '\0'; cacheDirNoise[0] = '\0'; - std::string dformat = getCacheFileEnding(mmd->domain->cache_data_format); - std::string nformat = getCacheFileEnding(mmd->domain->cache_noise_format); + string dformat = getCacheFileEnding(mds->cache_data_format); + string nformat = getCacheFileEnding(mds->cache_noise_format); - bool final_cache = (mmd->domain->cache_type == FLUID_DOMAIN_CACHE_FINAL); - std::string resumable_cache = (final_cache) ? "False" : "True"; + bool final_cache = (mds->cache_type == FLUID_DOMAIN_CACHE_FINAL); + string resumable_cache = (final_cache) ? "False" : "True"; - BLI_path_join(cacheDirData, - sizeof(cacheDirData), - mmd->domain->cache_directory, - FLUID_DOMAIN_DIR_DATA, - nullptr); - BLI_path_join(cacheDirNoise, - sizeof(cacheDirNoise), - mmd->domain->cache_directory, - FLUID_DOMAIN_DIR_NOISE, - nullptr); + BLI_path_join( + cacheDirData, sizeof(cacheDirData), mds->cache_directory, FLUID_DOMAIN_DIR_DATA, nullptr); + BLI_path_join( + cacheDirNoise, sizeof(cacheDirNoise), mds->cache_directory, FLUID_DOMAIN_DIR_NOISE, nullptr); BLI_path_make_safe(cacheDirData); BLI_path_make_safe(cacheDirNoise); @@ -1767,29 +1620,24 @@ bool MANTA::bakeNoise(FluidModifierData *mmd, int framenr) bool MANTA::bakeMesh(FluidModifierData *mmd, int framenr) { if (with_debug) - std::cout << "MANTA::bakeMesh()" << std::endl; + cout << "MANTA::bakeMesh()" << endl; - std::ostringstream ss; - std::vector<std::string> pythonCommands; + ostringstream ss; + vector<string> pythonCommands; + FluidDomainSettings *mds = mmd->domain; char cacheDirData[FILE_MAX], cacheDirMesh[FILE_MAX]; cacheDirData[0] = '\0'; cacheDirMesh[0] = '\0'; - std::string dformat = getCacheFileEnding(mmd->domain->cache_data_format); - std::string mformat = getCacheFileEnding(mmd->domain->cache_mesh_format); - std::string pformat = getCacheFileEnding(mmd->domain->cache_particle_format); + string dformat = getCacheFileEnding(mds->cache_data_format); + string mformat = getCacheFileEnding(mds->cache_mesh_format); + string pformat = getCacheFileEnding(mds->cache_particle_format); - BLI_path_join(cacheDirData, - sizeof(cacheDirData), - mmd->domain->cache_directory, - FLUID_DOMAIN_DIR_DATA, - nullptr); - BLI_path_join(cacheDirMesh, - sizeof(cacheDirMesh), - mmd->domain->cache_directory, - FLUID_DOMAIN_DIR_MESH, - nullptr); + BLI_path_join( + cacheDirData, sizeof(cacheDirData), mds->cache_directory, FLUID_DOMAIN_DIR_DATA, nullptr); + BLI_path_join( + cacheDirMesh, sizeof(cacheDirMesh), mds->cache_directory, FLUID_DOMAIN_DIR_MESH, nullptr); BLI_path_make_safe(cacheDirData); BLI_path_make_safe(cacheDirMesh); @@ -1805,29 +1653,27 @@ bool MANTA::bakeMesh(FluidModifierData *mmd, int framenr) bool MANTA::bakeParticles(FluidModifierData *mmd, int framenr) { if (with_debug) - std::cout << "MANTA::bakeParticles()" << std::endl; + cout << "MANTA::bakeParticles()" << endl; - std::ostringstream ss; - std::vector<std::string> pythonCommands; + ostringstream ss; + vector<string> pythonCommands; + FluidDomainSettings *mds = mmd->domain; char cacheDirData[FILE_MAX], cacheDirParticles[FILE_MAX]; cacheDirData[0] = '\0'; cacheDirParticles[0] = '\0'; - std::string dformat = getCacheFileEnding(mmd->domain->cache_data_format); - std::string pformat = getCacheFileEnding(mmd->domain->cache_particle_format); + string dformat = getCacheFileEnding(mds->cache_data_format); + string pformat = getCacheFileEnding(mds->cache_particle_format); - bool final_cache = (mmd->domain->cache_type == FLUID_DOMAIN_CACHE_FINAL); - std::string resumable_cache = (final_cache) ? "False" : "True"; + bool final_cache = (mds->cache_type == FLUID_DOMAIN_CACHE_FINAL); + string resumable_cache = (final_cache) ? "False" : "True"; - BLI_path_join(cacheDirData, - sizeof(cacheDirData), - mmd->domain->cache_directory, - FLUID_DOMAIN_DIR_DATA, - nullptr); + BLI_path_join( + cacheDirData, sizeof(cacheDirData), mds->cache_directory, FLUID_DOMAIN_DIR_DATA, nullptr); BLI_path_join(cacheDirParticles, sizeof(cacheDirParticles), - mmd->domain->cache_directory, + mds->cache_directory, FLUID_DOMAIN_DIR_PARTICLES, nullptr); BLI_path_make_safe(cacheDirData); @@ -1845,22 +1691,23 @@ bool MANTA::bakeParticles(FluidModifierData *mmd, int framenr) bool MANTA::bakeGuiding(FluidModifierData *mmd, int framenr) { if (with_debug) - std::cout << "MANTA::bakeGuiding()" << std::endl; + cout << "MANTA::bakeGuiding()" << endl; - std::ostringstream ss; - std::vector<std::string> pythonCommands; + ostringstream ss; + vector<string> pythonCommands; + FluidDomainSettings *mds = mmd->domain; char cacheDirGuiding[FILE_MAX]; cacheDirGuiding[0] = '\0'; - std::string gformat = getCacheFileEnding(mmd->domain->cache_data_format); + string gformat = getCacheFileEnding(mds->cache_data_format); - bool final_cache = (mmd->domain->cache_type == FLUID_DOMAIN_CACHE_FINAL); - std::string resumable_cache = (final_cache) ? "False" : "True"; + bool final_cache = (mds->cache_type == FLUID_DOMAIN_CACHE_FINAL); + string resumable_cache = (final_cache) ? "False" : "True"; BLI_path_join(cacheDirGuiding, sizeof(cacheDirGuiding), - mmd->domain->cache_directory, + mds->cache_directory, FLUID_DOMAIN_DIR_GUIDE, nullptr); BLI_path_make_safe(cacheDirGuiding); @@ -1875,8 +1722,8 @@ bool MANTA::bakeGuiding(FluidModifierData *mmd, int framenr) bool MANTA::updateVariables(FluidModifierData *mmd) { - std::string tmpString, finalString; - std::vector<std::string> pythonCommands; + string tmpString, finalString; + vector<string> pythonCommands; tmpString += fluid_variables; if (mUsingSmoke) @@ -1906,13 +1753,15 @@ bool MANTA::updateVariables(FluidModifierData *mmd) void MANTA::exportSmokeScript(FluidModifierData *mmd) { if (with_debug) - std::cout << "MANTA::exportSmokeScript()" << std::endl; + cout << "MANTA::exportSmokeScript()" << endl; char cacheDir[FILE_MAX] = "\0"; char cacheDirScript[FILE_MAX] = "\0"; + FluidDomainSettings *mds = mmd->domain; + BLI_path_join( - cacheDir, sizeof(cacheDir), mmd->domain->cache_directory, FLUID_DOMAIN_DIR_SCRIPT, nullptr); + cacheDir, sizeof(cacheDir), mds->cache_directory, FLUID_DOMAIN_DIR_SCRIPT, nullptr); BLI_path_make_safe(cacheDir); /* Create 'script' subdir if it does not exist already */ BLI_dir_create_recursive(cacheDir); @@ -1920,16 +1769,16 @@ void MANTA::exportSmokeScript(FluidModifierData *mmd) cacheDirScript, sizeof(cacheDirScript), cacheDir, FLUID_DOMAIN_SMOKE_SCRIPT, nullptr); BLI_path_make_safe(cacheDir); - bool noise = mmd->domain->flags & FLUID_DOMAIN_USE_NOISE; - bool heat = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_HEAT; - bool colors = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_COLORS; - bool fire = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_FIRE; - bool obstacle = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE; - bool guiding = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_GUIDE; - bool invel = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_INVEL; - bool outflow = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW; + bool noise = mds->flags & FLUID_DOMAIN_USE_NOISE; + bool heat = mds->active_fields & FLUID_DOMAIN_ACTIVE_HEAT; + bool colors = mds->active_fields & FLUID_DOMAIN_ACTIVE_COLORS; + bool fire = mds->active_fields & FLUID_DOMAIN_ACTIVE_FIRE; + bool obstacle = mds->active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE; + bool guiding = mds->active_fields & FLUID_DOMAIN_ACTIVE_GUIDE; + bool invel = mds->active_fields & FLUID_DOMAIN_ACTIVE_INVEL; + bool outflow = mds->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW; - std::string manta_script; + string manta_script; // Libraries manta_script += header_libraries + manta_import; @@ -2001,10 +1850,10 @@ void MANTA::exportSmokeScript(FluidModifierData *mmd) manta_script += header_main + smoke_standalone + fluid_standalone; // Fill in missing variables in script - std::string final_script = MANTA::parseScript(manta_script, mmd); + string final_script = MANTA::parseScript(manta_script, mmd); // Write script - std::ofstream myfile; + ofstream myfile; myfile.open(cacheDirScript); myfile << final_script; myfile.close(); @@ -2013,13 +1862,15 @@ void MANTA::exportSmokeScript(FluidModifierData *mmd) void MANTA::exportLiquidScript(FluidModifierData *mmd) { if (with_debug) - std::cout << "MANTA::exportLiquidScript()" << std::endl; + cout << "MANTA::exportLiquidScript()" << endl; char cacheDir[FILE_MAX] = "\0"; char cacheDirScript[FILE_MAX] = "\0"; + FluidDomainSettings *mds = mmd->domain; + BLI_path_join( - cacheDir, sizeof(cacheDir), mmd->domain->cache_directory, FLUID_DOMAIN_DIR_SCRIPT, nullptr); + cacheDir, sizeof(cacheDir), mds->cache_directory, FLUID_DOMAIN_DIR_SCRIPT, nullptr); BLI_path_make_safe(cacheDir); /* Create 'script' subdir if it does not exist already */ BLI_dir_create_recursive(cacheDir); @@ -2027,18 +1878,18 @@ void MANTA::exportLiquidScript(FluidModifierData *mmd) cacheDirScript, sizeof(cacheDirScript), cacheDir, FLUID_DOMAIN_LIQUID_SCRIPT, nullptr); BLI_path_make_safe(cacheDirScript); - bool mesh = mmd->domain->flags & FLUID_DOMAIN_USE_MESH; - bool drops = mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY; - bool bubble = mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_BUBBLE; - bool floater = mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_FOAM; - bool tracer = mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_TRACER; - bool obstacle = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE; - bool fractions = mmd->domain->flags & FLUID_DOMAIN_USE_FRACTIONS; - bool guiding = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_GUIDE; - bool invel = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_INVEL; - bool outflow = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW; + bool mesh = mds->flags & FLUID_DOMAIN_USE_MESH; + bool drops = mds->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY; + bool bubble = mds->particle_type & FLUID_DOMAIN_PARTICLE_BUBBLE; + bool floater = mds->particle_type & FLUID_DOMAIN_PARTICLE_FOAM; + bool tracer = mds->particle_type & FLUID_DOMAIN_PARTICLE_TRACER; + bool obstacle = mds->active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE; + bool fractions = mds->flags & FLUID_DOMAIN_USE_FRACTIONS; + bool guiding = mds->active_fields & FLUID_DOMAIN_ACTIVE_GUIDE; + bool invel = mds->active_fields & FLUID_DOMAIN_ACTIVE_INVEL; + bool outflow = mds->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW; - std::string manta_script; + string manta_script; // Libraries manta_script += header_libraries + manta_import; @@ -2108,10 +1959,10 @@ void MANTA::exportLiquidScript(FluidModifierData *mmd) manta_script += header_main + liquid_standalone + fluid_standalone; // Fill in missing variables in script - std::string final_script = MANTA::parseScript(manta_script, mmd); + string final_script = MANTA::parseScript(manta_script, mmd); // Write script - std::ofstream myfile; + ofstream myfile; myfile.open(cacheDirScript); myfile << final_script; myfile.close(); @@ -2124,14 +1975,12 @@ void MANTA::exportLiquidScript(FluidModifierData *mmd) * * Important! Return value: New reference or nullptr * Caller of this function needs to handle reference count of returned object. */ -static PyObject *callPythonFunction(std::string varName, - std::string functionName, - bool isAttribute = false) +static PyObject *callPythonFunction(string varName, string functionName, bool isAttribute = false) { if ((varName == "") || (functionName == "")) { if (MANTA::with_debug) - std::cout << "Missing Python variable name and/or function name -- name is: " << varName - << ", function name is: " << functionName << std::endl; + cout << "Missing Python variable name and/or function name -- name is: " << varName + << ", function name is: " << functionName << endl; return nullptr; } @@ -2185,8 +2034,8 @@ static void *pyObjectToPointer(PyObject *inputObject) Py_DECREF(inputObject); - std::string str(result); - std::istringstream in(str); + string str(result); + istringstream in(str); void *dataPointer = nullptr; in >> dataPointer; @@ -2233,11 +2082,11 @@ static long pyObjectToLong(PyObject *inputObject) int MANTA::getFrame() { if (with_debug) - std::cout << "MANTA::getFrame()" << std::endl; + cout << "MANTA::getFrame()" << endl; - std::string func = "frame"; - std::string id = std::to_string(mCurrentID); - std::string solver = "s" + id; + string func = "frame"; + string id = to_string(mCurrentID); + string solver = "s" + id; return pyObjectToLong(callPythonFunction(solver, func, true)); } @@ -2245,11 +2094,11 @@ int MANTA::getFrame() float MANTA::getTimestep() { if (with_debug) - std::cout << "MANTA::getTimestep()" << std::endl; + cout << "MANTA::getTimestep()" << endl; - std::string func = "timestep"; - std::string id = std::to_string(mCurrentID); - std::string solver = "s" + id; + string func = "timestep"; + string id = to_string(mCurrentID); + string solver = "s" + id; return (float)pyObjectToDouble(callPythonFunction(solver, func, true)); } @@ -2263,10 +2112,10 @@ bool MANTA::needsRealloc(FluidModifierData *mmd) void MANTA::adaptTimestep() { if (with_debug) - std::cout << "MANTA::adaptTimestep()" << std::endl; + cout << "MANTA::adaptTimestep()" << endl; - std::vector<std::string> pythonCommands; - std::ostringstream ss; + vector<string> pythonCommands; + ostringstream ss; ss << "fluid_adapt_time_step_" << mCurrentID << "()"; pythonCommands.push_back(ss.str()); @@ -2274,14 +2123,14 @@ void MANTA::adaptTimestep() runPythonString(pythonCommands); } -bool MANTA::updateMeshFromFile(std::string filename) +bool MANTA::updateMeshFromFile(string filename) { - std::string fname(filename); - std::string::size_type idx; + string fname(filename); + string::size_type idx; idx = fname.rfind('.'); - if (idx != std::string::npos) { - std::string extension = fname.substr(idx + 1); + if (idx != string::npos) { + string extension = fname.substr(idx + 1); if (extension.compare("gz") == 0) return updateMeshFromBobj(filename); @@ -2290,27 +2139,25 @@ bool MANTA::updateMeshFromFile(std::string filename) else if (extension.compare("uni") == 0) return updateMeshFromUni(filename); else - std::cerr << "Fluid Error -- updateMeshFromFile(): Invalid file extension in file: " - << filename << std::endl; + cerr << "Fluid Error -- updateMeshFromFile(): Invalid file extension in file: " << filename + << endl; } else { - std::cerr << "Fluid Error -- updateMeshFromFile(): Unable to open file: " << filename - << std::endl; + cerr << "Fluid Error -- updateMeshFromFile(): Unable to open file: " << filename << endl; } return false; } -bool MANTA::updateMeshFromBobj(std::string filename) +bool MANTA::updateMeshFromBobj(string filename) { if (with_debug) - std::cout << "MANTA::updateMeshFromBobj()" << std::endl; + cout << "MANTA::updateMeshFromBobj()" << endl; gzFile gzf; gzf = (gzFile)BLI_gzopen(filename.c_str(), "rb1"); // do some compression if (!gzf) { - std::cerr << "Fluid Error -- updateMeshFromBobj(): Unable to open file: " << filename - << std::endl; + cerr << "Fluid Error -- updateMeshFromBobj(): Unable to open file: " << filename << endl; return false; } @@ -2319,15 +2166,14 @@ bool MANTA::updateMeshFromBobj(std::string filename) // Num vertices readBytes = gzread(gzf, &numBuffer, sizeof(int)); if (!readBytes) { - std::cerr - << "Fluid Error -- updateMeshFromBobj(): Unable to read number of mesh vertices from " - << filename << std::endl; + cerr << "Fluid Error -- updateMeshFromBobj(): Unable to read number of mesh vertices from " + << filename << endl; gzclose(gzf); return false; } if (with_debug) - std::cout << "read mesh , num verts: " << numBuffer << " , in file: " << filename << std::endl; + cout << "read mesh , num verts: " << numBuffer << " , in file: " << filename << endl; int numChunks = (int)(ceil((float)numBuffer / NODE_CHUNK)); int readLen, readStart, readEnd, k; @@ -2348,8 +2194,8 @@ bool MANTA::updateMeshFromBobj(std::string filename) readBytes = gzread(gzf, bufferVerts, readLen * sizeof(float) * 3); if (!readBytes) { - std::cerr << "Fluid Error -- updateMeshFromBobj(): Unable to read mesh vertices from " - << filename << std::endl; + cerr << "Fluid Error -- updateMeshFromBobj(): Unable to read mesh vertices from " + << filename << endl; MEM_freeN(bufferVerts); gzclose(gzf); return false; @@ -2361,7 +2207,7 @@ bool MANTA::updateMeshFromBobj(std::string filename) CLAMP(readEnd, 0, numBuffer); k = 0; - for (std::vector<MANTA::Node>::size_type j = readStart; j < readEnd; j++, k += 3) { + for (vector<MANTA::Node>::size_type j = readStart; j < readEnd; j++, k += 3) { mMeshNodes->at(j).pos[0] = bufferVerts[k]; mMeshNodes->at(j).pos[1] = bufferVerts[k + 1]; mMeshNodes->at(j).pos[2] = bufferVerts[k + 2]; @@ -2374,15 +2220,14 @@ bool MANTA::updateMeshFromBobj(std::string filename) // Num normals readBytes = gzread(gzf, &numBuffer, sizeof(int)); if (!readBytes) { - std::cerr << "Fluid Error -- updateMeshFromBobj(): Unable to read number of mesh normals from " - << filename << std::endl; + cerr << "Fluid Error -- updateMeshFromBobj(): Unable to read number of mesh normals from " + << filename << endl; gzclose(gzf); return false; } if (with_debug) - std::cout << "read mesh , num normals : " << numBuffer << " , in file: " << filename - << std::endl; + cout << "read mesh , num normals : " << numBuffer << " , in file: " << filename << endl; if (numBuffer) { // Normals @@ -2401,8 +2246,8 @@ bool MANTA::updateMeshFromBobj(std::string filename) readBytes = gzread(gzf, bufferNormals, readLen * sizeof(float) * 3); if (!readBytes) { - std::cerr << "Fluid Error -- updateMeshFromBobj(): Unable to read mesh normals from " - << filename << std::endl; + cerr << "Fluid Error -- updateMeshFromBobj(): Unable to read mesh normals from " + << filename << endl; MEM_freeN(bufferNormals); gzclose(gzf); return false; @@ -2414,7 +2259,7 @@ bool MANTA::updateMeshFromBobj(std::string filename) CLAMP(readEnd, 0, numBuffer); k = 0; - for (std::vector<MANTA::Node>::size_type j = readStart; j < readEnd; j++, k += 3) { + for (vector<MANTA::Node>::size_type j = readStart; j < readEnd; j++, k += 3) { mMeshNodes->at(j).normal[0] = bufferNormals[k]; mMeshNodes->at(j).normal[1] = bufferNormals[k + 1]; mMeshNodes->at(j).normal[2] = bufferNormals[k + 2]; @@ -2427,16 +2272,15 @@ bool MANTA::updateMeshFromBobj(std::string filename) // Num triangles readBytes = gzread(gzf, &numBuffer, sizeof(int)); if (!readBytes) { - std::cerr - << "Fluid Error -- updateMeshFromBobj(): Unable to read number of mesh triangles from " - << filename << std::endl; + cerr << "Fluid Error -- updateMeshFromBobj(): Unable to read number of mesh triangles from " + << filename << endl; gzclose(gzf); return false; } if (with_debug) - std::cout << "Fluid: Read mesh , num triangles : " << numBuffer << " , in file: " << filename - << std::endl; + cout << "Fluid: Read mesh , num triangles : " << numBuffer << " , in file: " << filename + << endl; numChunks = (int)(ceil((float)numBuffer / TRIANGLE_CHUNK)); @@ -2456,8 +2300,8 @@ bool MANTA::updateMeshFromBobj(std::string filename) readBytes = gzread(gzf, bufferTriangles, readLen * sizeof(int) * 3); if (!readBytes) { - std::cerr << "Fluid Error -- updateMeshFromBobj(): Unable to read mesh triangles from " - << filename << std::endl; + cerr << "Fluid Error -- updateMeshFromBobj(): Unable to read mesh triangles from " + << filename << endl; MEM_freeN(bufferTriangles); gzclose(gzf); return false; @@ -2469,7 +2313,7 @@ bool MANTA::updateMeshFromBobj(std::string filename) CLAMP(readEnd, 0, numBuffer); k = 0; - for (std::vector<MANTA::Triangle>::size_type j = readStart; j < readEnd; j++, k += 3) { + for (vector<MANTA::Triangle>::size_type j = readStart; j < readEnd; j++, k += 3) { mMeshTriangles->at(j).c[0] = bufferTriangles[k]; mMeshTriangles->at(j).c[1] = bufferTriangles[k + 1]; mMeshTriangles->at(j).c[2] = bufferTriangles[k + 2]; @@ -2481,24 +2325,23 @@ bool MANTA::updateMeshFromBobj(std::string filename) return (gzclose(gzf) == Z_OK); } -bool MANTA::updateMeshFromObj(std::string filename) +bool MANTA::updateMeshFromObj(string filename) { if (with_debug) - std::cout << "MANTA::updateMeshFromObj()" << std::endl; + cout << "MANTA::updateMeshFromObj()" << endl; - std::ifstream ifs(filename); + ifstream ifs(filename); float fbuffer[3]; int ibuffer[3]; int cntVerts = 0, cntNormals = 0, cntTris = 0; if (!ifs.good()) { - std::cerr << "Fluid Error -- updateMeshFromObj(): Unable to open file: " << filename - << std::endl; + cerr << "Fluid Error -- updateMeshFromObj(): Unable to open file: " << filename << endl; return false; } while (ifs.good() && !ifs.eof()) { - std::string id; + string id; ifs >> id; if (id[0] == '#') { @@ -2512,8 +2355,8 @@ bool MANTA::updateMeshFromObj(std::string filename) else if (id == "vn") { // normals if (getNumVertices() != cntVerts) { - std::cerr << "Fluid Error -- updateMeshFromObj(): Invalid number of mesh nodes in file: " - << filename << std::endl; + cerr << "Fluid Error -- updateMeshFromObj(): Invalid number of mesh nodes in file: " + << filename << endl; return false; } @@ -2536,20 +2379,20 @@ bool MANTA::updateMeshFromObj(std::string filename) } else if (id == "g") { // group - std::string group; + string group; ifs >> group; } else if (id == "f") { // face - std::string face; + string face; for (int i = 0; i < 3; i++) { ifs >> face; - if (face.find('/') != std::string::npos) + if (face.find('/') != string::npos) face = face.substr(0, face.find('/')); // ignore other indices int idx = atoi(face.c_str()) - 1; if (idx < 0) { - std::cerr << "Fluid Error -- updateMeshFromObj(): Invalid face encountered in file: " - << filename << std::endl; + cerr << "Fluid Error -- updateMeshFromObj(): Invalid face encountered in file: " + << filename << endl; return false; } ibuffer[i] = idx; @@ -2571,10 +2414,10 @@ bool MANTA::updateMeshFromObj(std::string filename) return true; } -bool MANTA::updateMeshFromUni(std::string filename) +bool MANTA::updateMeshFromUni(string filename) { if (with_debug) - std::cout << "MANTA::updateMeshFromUni()" << std::endl; + cout << "MANTA::updateMeshFromUni()" << endl; gzFile gzf; float fbuffer[4]; @@ -2582,8 +2425,7 @@ bool MANTA::updateMeshFromUni(std::string filename) gzf = (gzFile)BLI_gzopen(filename.c_str(), "rb1"); // do some compression if (!gzf) { - std::cerr << "Fluid Error -- updateMeshFromUni(): Unable to open file: " << filename - << std::endl; + cerr << "Fluid Error -- updateMeshFromUni(): Unable to open file: " << filename << endl; return false; } @@ -2591,13 +2433,13 @@ bool MANTA::updateMeshFromUni(std::string filename) char file_magic[5] = {0, 0, 0, 0, 0}; readBytes = gzread(gzf, file_magic, 4); if (!readBytes) { - std::cerr << "Fluid Error -- updateMeshFromUni(): Unable to read header in file: " << filename - << std::endl; + cerr << "Fluid Error -- updateMeshFromUni(): Unable to read header in file: " << filename + << endl; gzclose(gzf); return false; } - std::vector<pVel> *velocityPointer = mMeshVelocities; + vector<pVel> *velocityPointer = mMeshVelocities; // mdata uni header const int STR_LEN_PDATA = 256; @@ -2613,19 +2455,18 @@ bool MANTA::updateMeshFromUni(std::string filename) gzread(gzf, ×tamp, sizeof(unsigned long long)); if (with_debug) - std::cout << "Fluid: Read " << ibuffer[0] << " vertices in file: " << filename << std::endl; + cout << "Fluid: Read " << ibuffer[0] << " vertices in file: " << filename << endl; // Sanity checks const int meshSize = sizeof(float) * 3 + sizeof(int); if (!(bytesPerElement == meshSize) && (elementType == 0)) { - std::cerr << "Fluid Error -- updateMeshFromUni(): Invalid header in file: " << filename - << std::endl; + cerr << "Fluid Error -- updateMeshFromUni(): Invalid header in file: " << filename << endl; gzclose(gzf); return false; } if (!ibuffer[0]) { // Any vertices present? - std::cerr << "Fluid Error -- updateMeshFromUni(): No vertices present in file: " << filename - << std::endl; + cerr << "Fluid Error -- updateMeshFromUni(): No vertices present in file: " << filename + << endl; gzclose(gzf); return false; } @@ -2640,7 +2481,7 @@ bool MANTA::updateMeshFromUni(std::string filename) velocityPointer->resize(numParticles); MANTA::pVel *bufferPVel; - for (std::vector<pVel>::iterator it = velocityPointer->begin(); it != velocityPointer->end(); + for (vector<pVel>::iterator it = velocityPointer->begin(); it != velocityPointer->end(); ++it) { gzread(gzf, fbuffer, sizeof(float) * 3); bufferPVel = (MANTA::pVel *)fbuffer; @@ -2652,44 +2493,42 @@ bool MANTA::updateMeshFromUni(std::string filename) return (gzclose(gzf) == Z_OK); } -bool MANTA::updateParticlesFromFile(std::string filename, bool isSecondarySys, bool isVelData) +bool MANTA::updateParticlesFromFile(string filename, bool isSecondarySys, bool isVelData) { if (with_debug) - std::cout << "MANTA::updateParticlesFromFile()" << std::endl; + cout << "MANTA::updateParticlesFromFile()" << endl; - std::string fname(filename); - std::string::size_type idx; + string fname(filename); + string::size_type idx; idx = fname.rfind('.'); - if (idx != std::string::npos) { - std::string extension = fname.substr(idx + 1); + if (idx != string::npos) { + string extension = fname.substr(idx + 1); if (extension.compare("uni") == 0) return updateParticlesFromUni(filename, isSecondarySys, isVelData); else - std::cerr << "Fluid Error -- updateParticlesFromFile(): Invalid file extension in file: " - << filename << std::endl; + cerr << "Fluid Error -- updateParticlesFromFile(): Invalid file extension in file: " + << filename << endl; return false; } else { - std::cerr << "Fluid Error -- updateParticlesFromFile(): Unable to open file: " << filename - << std::endl; + cerr << "Fluid Error -- updateParticlesFromFile(): Unable to open file: " << filename << endl; return false; } } -bool MANTA::updateParticlesFromUni(std::string filename, bool isSecondarySys, bool isVelData) +bool MANTA::updateParticlesFromUni(string filename, bool isSecondarySys, bool isVelData) { if (with_debug) - std::cout << "MANTA::updateParticlesFromUni()" << std::endl; + cout << "MANTA::updateParticlesFromUni()" << endl; gzFile gzf; int ibuffer[4]; gzf = (gzFile)BLI_gzopen(filename.c_str(), "rb1"); // do some compression if (!gzf) { - std::cerr << "Fluid Error -- updateParticlesFromUni(): Unable to open file: " << filename - << std::endl; + cerr << "Fluid Error -- updateParticlesFromUni(): Unable to open file: " << filename << endl; return false; } @@ -2697,24 +2536,24 @@ bool MANTA::updateParticlesFromUni(std::string filename, bool isSecondarySys, bo char file_magic[5] = {0, 0, 0, 0, 0}; readBytes = gzread(gzf, file_magic, 4); if (!readBytes) { - std::cerr << "Fluid Error -- updateParticlesFromUni(): Unable to read header in file: " - << filename << std::endl; + cerr << "Fluid Error -- updateParticlesFromUni(): Unable to read header in file: " << filename + << endl; gzclose(gzf); return false; } if (!strcmp(file_magic, "PB01")) { - std::cerr << "Fluid Error -- updateParticlesFromUni(): Particle uni file format v01 not " - "supported anymore." - << std::endl; + cerr << "Fluid Error -- updateParticlesFromUni(): Particle uni file format v01 not " + "supported anymore." + << endl; gzclose(gzf); return false; } // Pointer to FLIP system or to secondary particle system - std::vector<pData> *dataPointer = nullptr; - std::vector<pVel> *velocityPointer = nullptr; - std::vector<float> *lifePointer = nullptr; + vector<pData> *dataPointer = nullptr; + vector<pVel> *velocityPointer = nullptr; + vector<float> *lifePointer = nullptr; if (isSecondarySys) { dataPointer = mSndParticleData; @@ -2740,19 +2579,19 @@ bool MANTA::updateParticlesFromUni(std::string filename, bool isSecondarySys, bo gzread(gzf, ×tamp, sizeof(unsigned long long)); if (with_debug) - std::cout << "Fluid: Read " << ibuffer[0] << " particles in file: " << filename << std::endl; + cout << "Fluid: Read " << ibuffer[0] << " particles in file: " << filename << endl; // Sanity checks const int partSysSize = sizeof(float) * 3 + sizeof(int); if (!(bytesPerElement == partSysSize) && (elementType == 0)) { - std::cerr << "Fluid Error -- updateParticlesFromUni(): Invalid header in file: " << filename - << std::endl; + cerr << "Fluid Error -- updateParticlesFromUni(): Invalid header in file: " << filename + << endl; gzclose(gzf); return false; } if (!ibuffer[0]) { // Any particles present? if (with_debug) - std::cout << "Fluid: No particles present in file: " << filename << std::endl; + cout << "Fluid: No particles present in file: " << filename << endl; gzclose(gzf); return true; // return true since having no particles in a cache file is valid } @@ -2780,9 +2619,8 @@ bool MANTA::updateParticlesFromUni(std::string filename, bool isSecondarySys, bo readBytes = gzread(gzf, bufferPData, readLen * sizeof(pData)); if (!readBytes) { - std::cerr - << "Fluid Error -- updateParticlesFromUni(): Unable to read particle data in file: " - << filename << std::endl; + cerr << "Fluid Error -- updateParticlesFromUni(): Unable to read particle data in file: " + << filename << endl; MEM_freeN(bufferPData); gzclose(gzf); return false; @@ -2794,7 +2632,7 @@ bool MANTA::updateParticlesFromUni(std::string filename, bool isSecondarySys, bo CLAMP(readEnd, 0, numParticles); int k = 0; - for (std::vector<MANTA::pData>::size_type j = readStart; j < readEnd; j++, k++) { + for (vector<MANTA::pData>::size_type j = readStart; j < readEnd; j++, k++) { dataPointer->at(j).pos[0] = bufferPData[k].pos[0]; dataPointer->at(j).pos[1] = bufferPData[k].pos[1]; dataPointer->at(j).pos[2] = bufferPData[k].pos[2]; @@ -2821,9 +2659,9 @@ bool MANTA::updateParticlesFromUni(std::string filename, bool isSecondarySys, bo readBytes = gzread(gzf, bufferPVel, readLen * sizeof(pVel)); if (!readBytes) { - std::cerr << "Fluid Error -- updateParticlesFromUni(): Unable to read particle velocities " - "in file: " - << filename << std::endl; + cerr << "Fluid Error -- updateParticlesFromUni(): Unable to read particle velocities " + "in file: " + << filename << endl; MEM_freeN(bufferPVel); gzclose(gzf); return false; @@ -2835,7 +2673,7 @@ bool MANTA::updateParticlesFromUni(std::string filename, bool isSecondarySys, bo CLAMP(readEnd, 0, numParticles); int k = 0; - for (std::vector<MANTA::pVel>::size_type j = readStart; j < readEnd; j++, k++) { + for (vector<MANTA::pVel>::size_type j = readStart; j < readEnd; j++, k++) { velocityPointer->at(j).pos[0] = bufferPVel[k].pos[0]; velocityPointer->at(j).pos[1] = bufferPVel[k].pos[1]; velocityPointer->at(j).pos[2] = bufferPVel[k].pos[2]; @@ -2860,9 +2698,8 @@ bool MANTA::updateParticlesFromUni(std::string filename, bool isSecondarySys, bo readBytes = gzread(gzf, bufferPLife, readLen * sizeof(float)); if (!readBytes) { - std::cerr - << "Fluid Error -- updateParticlesFromUni(): Unable to read particle life in file: " - << filename << std::endl; + cerr << "Fluid Error -- updateParticlesFromUni(): Unable to read particle life in file: " + << filename << endl; MEM_freeN(bufferPLife); gzclose(gzf); return false; @@ -2874,7 +2711,7 @@ bool MANTA::updateParticlesFromUni(std::string filename, bool isSecondarySys, bo CLAMP(readEnd, 0, numParticles); int k = 0; - for (std::vector<float>::size_type j = readStart; j < readEnd; j++, k++) { + for (vector<float>::size_type j = readStart; j < readEnd; j++, k++) { lifePointer->at(j) = bufferPLife[k]; } todoParticles -= readLen; @@ -2884,24 +2721,24 @@ bool MANTA::updateParticlesFromUni(std::string filename, bool isSecondarySys, bo return (gzclose(gzf) == Z_OK); } -bool MANTA::updateGridFromFile(std::string filename, float *grid, bool isNoise) +bool MANTA::updateGridFromFile(string filename, float *grid, bool isNoise) { if (with_debug) - std::cout << "MANTA::updateGridFromFile()" << std::endl; + cout << "MANTA::updateGridFromFile()" << endl; if (!grid) { - std::cerr << "Fluid Error -- updateGridFromFile(): Cannot read into uninitialized grid (grid " - "is null)." - << std::endl; + cerr << "Fluid Error -- updateGridFromFile(): Cannot read into uninitialized grid (grid " + "is null)." + << endl; return false; } - std::string fname(filename); - std::string::size_type idx; + string fname(filename); + string::size_type idx; idx = fname.rfind('.'); - if (idx != std::string::npos) { - std::string extension = fname.substr(idx + 1); + if (idx != string::npos) { + string extension = fname.substr(idx + 1); if (extension.compare("uni") == 0) return updateGridFromUni(filename, grid, isNoise); @@ -2912,29 +2749,27 @@ bool MANTA::updateGridFromFile(std::string filename, float *grid, bool isNoise) else if (extension.compare("raw") == 0) return updateGridFromRaw(filename, grid, isNoise); else - std::cerr << "Fluid Error -- updateGridFromFile(): Invalid file extension in file: " - << filename << std::endl; + cerr << "Fluid Error -- updateGridFromFile(): Invalid file extension in file: " << filename + << endl; return false; } else { - std::cerr << "Fluid Error -- updateGridFromFile(): Unable to open file: " << filename - << std::endl; + cerr << "Fluid Error -- updateGridFromFile(): Unable to open file: " << filename << endl; return false; } } -bool MANTA::updateGridFromUni(std::string filename, float *grid, bool isNoise) +bool MANTA::updateGridFromUni(string filename, float *grid, bool isNoise) { if (with_debug) - std::cout << "MANTA::updateGridFromUni()" << std::endl; + cout << "MANTA::updateGridFromUni()" << endl; gzFile gzf; int ibuffer[4]; gzf = (gzFile)BLI_gzopen(filename.c_str(), "rb1"); if (!gzf) { - std::cerr << "Fluid Error -- updateGridFromUni(): Unable to open file: " << filename - << std::endl; + cerr << "Fluid Error -- updateGridFromUni(): Unable to open file: " << filename << endl; return false; } @@ -2942,32 +2777,29 @@ bool MANTA::updateGridFromUni(std::string filename, float *grid, bool isNoise) char file_magic[5] = {0, 0, 0, 0, 0}; readBytes = gzread(gzf, file_magic, 4); if (!readBytes) { - std::cerr << "Fluid Error -- updateGridFromUni(): Unable to read header in file: " << filename - << std::endl; + cerr << "Fluid Error -- updateGridFromUni(): Unable to read header in file: " << filename + << endl; gzclose(gzf); return false; } if (!strcmp(file_magic, "DDF2")) { - std::cerr - << "Fluid Error -- updateGridFromUni(): Grid uni file format DDF2 not supported anymore." - << std::endl; + cerr << "Fluid Error -- updateGridFromUni(): Grid uni file format DDF2 not supported anymore." + << endl; gzclose(gzf); return false; } if (!strcmp(file_magic, "MNT1")) { - std::cerr - << "Fluid Error -- updateGridFromUni(): Grid uni file format MNT1 not supported anymore." - << std::endl; + cerr << "Fluid Error -- updateGridFromUni(): Grid uni file format MNT1 not supported anymore." + << endl; gzclose(gzf); return false; } if (!strcmp(file_magic, "MNT2")) { - std::cerr - << "Fluid Error -- updateGridFromUni(): Grid uni file format MNT2 not supported anymore." - << std::endl; + cerr << "Fluid Error -- updateGridFromUni(): Grid uni file format MNT2 not supported anymore." + << endl; gzclose(gzf); return false; } @@ -2992,13 +2824,12 @@ bool MANTA::updateGridFromUni(std::string filename, float *grid, bool isNoise) int resZ = (isNoise) ? mResZNoise : mResZ; if (with_debug) - std::cout << "Fluid: Read " << ibuffer[3] << " grid type in file: " << filename << std::endl; + cout << "Fluid: Read " << ibuffer[3] << " grid type in file: " << filename << endl; // Sanity checks if (ibuffer[0] != resX || ibuffer[1] != resY || ibuffer[2] != resZ) { - std::cout << "Fluid: Grid dim doesn't match, read: (" << ibuffer[0] << ", " << ibuffer[1] - << ", " << ibuffer[2] << ") vs setup: (" << resX << ", " << resY << ", " << resZ - << ")" << std::endl; + cout << "Fluid: Grid dim doesn't match, read: (" << ibuffer[0] << ", " << ibuffer[1] << ", " + << ibuffer[2] << ") vs setup: (" << resX << ", " << resY << ", " << resZ << ")" << endl; gzclose(gzf); return false; } @@ -3009,16 +2840,16 @@ bool MANTA::updateGridFromUni(std::string filename, float *grid, bool isNoise) } if (with_debug) - std::cout << "Fluid: Read successfully: " << filename << std::endl; + cout << "Fluid: Read successfully: " << filename << endl; return (gzclose(gzf) == Z_OK); } #if OPENVDB == 1 -bool MANTA::updateGridFromVDB(std::string filename, float *grid, bool isNoise) +bool MANTA::updateGridFromVDB(string filename, float *grid, bool isNoise) { if (with_debug) - std::cout << "MANTA::updateGridFromVDB()" << std::endl; + cout << "MANTA::updateGridFromVDB()" << endl; openvdb::initialize(); openvdb::io::File file(filename); @@ -3026,8 +2857,8 @@ bool MANTA::updateGridFromVDB(std::string filename, float *grid, bool isNoise) file.open(); } catch (const openvdb::IoError &) { - std::cerr << "Fluid Error -- updateGridFromVDB(): IOError, invalid OpenVDB file: " << filename - << std::endl; + cerr << "Fluid Error -- updateGridFromVDB(): IOError, invalid OpenVDB file: " << filename + << endl; return false; } @@ -3059,17 +2890,17 @@ bool MANTA::updateGridFromVDB(std::string filename, float *grid, bool isNoise) } #endif -bool MANTA::updateGridFromRaw(std::string filename, float *grid, bool isNoise) +bool MANTA::updateGridFromRaw(string filename, float *grid, bool isNoise) { if (with_debug) - std::cout << "MANTA::updateGridFromRaw()" << std::endl; + cout << "MANTA::updateGridFromRaw()" << endl; gzFile gzf; int expectedBytes, readBytes; gzf = (gzFile)BLI_gzopen(filename.c_str(), "rb"); if (!gzf) { - std::cout << "MANTA::updateGridFromRaw(): unable to open file" << std::endl; + cout << "MANTA::updateGridFromRaw(): unable to open file" << endl; return false; } @@ -3080,8 +2911,7 @@ bool MANTA::updateGridFromRaw(std::string filename, float *grid, bool isNoise) expectedBytes = sizeof(float) * resX * resY * resZ; readBytes = gzread(gzf, grid, expectedBytes); if (!readBytes) { - std::cerr << "Fluid Error -- updateGridFromRaw(): Unable to read raw file: " << filename - << std::endl; + cerr << "Fluid Error -- updateGridFromRaw(): Unable to read raw file: " << filename << endl; gzclose(gzf); return false; } @@ -3094,25 +2924,25 @@ bool MANTA::updateGridFromRaw(std::string filename, float *grid, bool isNoise) void MANTA::updatePointers() { if (with_debug) - std::cout << "MANTA::updatePointers()" << std::endl; - - std::string func = "getDataPointer"; - std::string funcNodes = "getNodesDataPointer"; - std::string funcTris = "getTrisDataPointer"; - - std::string id = std::to_string(mCurrentID); - std::string solver = "s" + id; - std::string parts = "pp" + id; - std::string snd = "sp" + id; - std::string mesh = "sm" + id; - std::string mesh2 = "mesh" + id; - std::string noise = "sn" + id; - std::string solver_ext = "_" + solver; - std::string parts_ext = "_" + parts; - std::string snd_ext = "_" + snd; - std::string mesh_ext = "_" + mesh; - std::string mesh_ext2 = "_" + mesh2; - std::string noise_ext = "_" + noise; + cout << "MANTA::updatePointers()" << endl; + + string func = "getDataPointer"; + string funcNodes = "getNodesDataPointer"; + string funcTris = "getTrisDataPointer"; + + string id = to_string(mCurrentID); + string solver = "s" + id; + string parts = "pp" + id; + string snd = "sp" + id; + string mesh = "sm" + id; + string mesh2 = "mesh" + id; + string noise = "sn" + id; + string solver_ext = "_" + solver; + string parts_ext = "_" + parts; + string snd_ext = "_" + snd; + string mesh_ext = "_" + mesh; + string mesh_ext2 = "_" + mesh2; + string noise_ext = "_" + noise; mFlags = (int *)pyObjectToPointer(callPythonFunction("flags" + solver_ext, func)); mPhiIn = (float *)pyObjectToPointer(callPythonFunction("phiIn" + solver_ext, func)); @@ -3199,27 +3029,27 @@ void MANTA::updatePointers() } if (mUsingLiquid) { mPhi = (float *)pyObjectToPointer(callPythonFunction("phi" + solver_ext, func)); - mFlipParticleData = (std::vector<pData> *)pyObjectToPointer( + mFlipParticleData = (vector<pData> *)pyObjectToPointer( callPythonFunction("pp" + solver_ext, func)); - mFlipParticleVelocity = (std::vector<pVel> *)pyObjectToPointer( + mFlipParticleVelocity = (vector<pVel> *)pyObjectToPointer( callPythonFunction("pVel" + parts_ext, func)); } if (mUsingLiquid && mUsingMesh) { - mMeshNodes = (std::vector<Node> *)pyObjectToPointer( + mMeshNodes = (vector<Node> *)pyObjectToPointer( callPythonFunction("mesh" + mesh_ext, funcNodes)); - mMeshTriangles = (std::vector<Triangle> *)pyObjectToPointer( + mMeshTriangles = (vector<Triangle> *)pyObjectToPointer( callPythonFunction("mesh" + mesh_ext, funcTris)); } if (mUsingLiquid && mUsingMVel) { - mMeshVelocities = (std::vector<pVel> *)pyObjectToPointer( + mMeshVelocities = (vector<pVel> *)pyObjectToPointer( callPythonFunction("mVel" + mesh_ext2, func)); } if (mUsingLiquid && (mUsingDrops | mUsingBubbles | mUsingFloats | mUsingTracers)) { - mSndParticleData = (std::vector<pData> *)pyObjectToPointer( + mSndParticleData = (vector<pData> *)pyObjectToPointer( callPythonFunction("ppSnd" + snd_ext, func)); - mSndParticleVelocity = (std::vector<pVel> *)pyObjectToPointer( + mSndParticleVelocity = (vector<pVel> *)pyObjectToPointer( callPythonFunction("pVelSnd" + parts_ext, func)); - mSndParticleLife = (std::vector<float> *)pyObjectToPointer( + mSndParticleLife = (vector<float> *)pyObjectToPointer( callPythonFunction("pLifeSnd" + parts_ext, func)); } @@ -3232,21 +3062,21 @@ void MANTA::updatePointers() bool MANTA::hasConfig(FluidModifierData *mmd, int framenr) { - std::string extension = FLUID_DOMAIN_EXTENSION_UNI; + string extension = FLUID_DOMAIN_EXTENSION_UNI; return BLI_exists( getFile(mmd, FLUID_DOMAIN_DIR_CONFIG, FLUID_DOMAIN_FILE_CONFIG, extension, framenr).c_str()); } bool MANTA::hasData(FluidModifierData *mmd, int framenr) { - std::string filename = (mUsingSmoke) ? FLUID_DOMAIN_FILE_DENSITY : FLUID_DOMAIN_FILE_PP; - std::string extension = getCacheFileEnding(mmd->domain->cache_data_format); + string filename = (mUsingSmoke) ? FLUID_DOMAIN_FILE_DENSITY : FLUID_DOMAIN_FILE_PP; + string extension = getCacheFileEnding(mmd->domain->cache_data_format); return BLI_exists(getFile(mmd, FLUID_DOMAIN_DIR_DATA, filename, extension, framenr).c_str()); } bool MANTA::hasNoise(FluidModifierData *mmd, int framenr) { - std::string extension = getCacheFileEnding(mmd->domain->cache_noise_format); + string extension = getCacheFileEnding(mmd->domain->cache_noise_format); return BLI_exists( getFile(mmd, FLUID_DOMAIN_DIR_NOISE, FLUID_DOMAIN_FILE_DENSITYNOISE, extension, framenr) .c_str()); @@ -3254,14 +3084,14 @@ bool MANTA::hasNoise(FluidModifierData *mmd, int framenr) bool MANTA::hasMesh(FluidModifierData *mmd, int framenr) { - std::string extension = getCacheFileEnding(mmd->domain->cache_mesh_format); + string extension = getCacheFileEnding(mmd->domain->cache_mesh_format); return BLI_exists( getFile(mmd, FLUID_DOMAIN_DIR_MESH, FLUID_DOMAIN_FILE_MESH, extension, framenr).c_str()); } bool MANTA::hasParticles(FluidModifierData *mmd, int framenr) { - std::string extension = getCacheFileEnding(mmd->domain->cache_particle_format); + string extension = getCacheFileEnding(mmd->domain->cache_particle_format); return BLI_exists( getFile(mmd, FLUID_DOMAIN_DIR_PARTICLES, FLUID_DOMAIN_FILE_PPSND, extension, framenr) .c_str()); @@ -3269,13 +3099,13 @@ bool MANTA::hasParticles(FluidModifierData *mmd, int framenr) bool MANTA::hasGuiding(FluidModifierData *mmd, int framenr, bool sourceDomain) { - std::string subdirectory = (sourceDomain) ? FLUID_DOMAIN_DIR_DATA : FLUID_DOMAIN_DIR_GUIDE; - std::string filename = (sourceDomain) ? FLUID_DOMAIN_FILE_VEL : FLUID_DOMAIN_FILE_GUIDEVEL; - std::string extension = getCacheFileEnding(mmd->domain->cache_data_format); + string subdirectory = (sourceDomain) ? FLUID_DOMAIN_DIR_DATA : FLUID_DOMAIN_DIR_GUIDE; + string filename = (sourceDomain) ? FLUID_DOMAIN_FILE_VEL : FLUID_DOMAIN_FILE_GUIDEVEL; + string extension = getCacheFileEnding(mmd->domain->cache_data_format); return BLI_exists(getFile(mmd, subdirectory, filename, extension, framenr).c_str()); } -std::string MANTA::getDirectory(FluidModifierData *mmd, std::string subdirectory) +string MANTA::getDirectory(FluidModifierData *mmd, string subdirectory) { char directory[FILE_MAX]; BLI_path_join( @@ -3284,15 +3114,12 @@ std::string MANTA::getDirectory(FluidModifierData *mmd, std::string subdirectory return directory; } -std::string MANTA::getFile(FluidModifierData *mmd, - std::string subdirectory, - std::string fname, - std::string extension, - int framenr) +string MANTA::getFile( + FluidModifierData *mmd, string subdirectory, string fname, string extension, int framenr) { char targetFile[FILE_MAX]; - std::string path = getDirectory(mmd, subdirectory); - std::string filename = fname + extension; + string path = getDirectory(mmd, subdirectory); + string filename = fname + extension; BLI_join_dirfile(targetFile, sizeof(targetFile), path.c_str(), filename.c_str()); BLI_path_frame(targetFile, framenr, 0); return targetFile; diff --git a/intern/mantaflow/intern/MANTA_main.h b/intern/mantaflow/intern/MANTA_main.h index 21946431f28..9b3fd6aa141 100644 --- a/intern/mantaflow/intern/MANTA_main.h +++ b/intern/mantaflow/intern/MANTA_main.h @@ -27,8 +27,14 @@ #include <atomic> #include <cassert> #include <string> +#include <unordered_map> #include <vector> +using std::atomic; +using std::string; +using std::unordered_map; +using std::vector; + struct MANTA { public: MANTA(int *res, struct FluidModifierData *mmd); @@ -58,20 +64,20 @@ struct MANTA { void step(struct FluidModifierData *mmd, int startFrame); // Grid initialization functions - void initHeat(struct FluidModifierData *mmd); - void initFire(struct FluidModifierData *mmd); - void initColors(struct FluidModifierData *mmd); - void initFireHigh(struct FluidModifierData *mmd); - void initColorsHigh(struct FluidModifierData *mmd); - void initLiquid(FluidModifierData *mmd); - void initLiquidMesh(FluidModifierData *mmd); - void initObstacle(FluidModifierData *mmd); - void initGuiding(FluidModifierData *mmd); - void initFractions(FluidModifierData *mmd); - void initInVelocity(FluidModifierData *mmd); - void initOutflow(FluidModifierData *mmd); - void initSndParts(FluidModifierData *mmd); - void initLiquidSndParts(FluidModifierData *mmd); + void initHeat(struct FluidModifierData *mmd = NULL); + void initFire(struct FluidModifierData *mmd = NULL); + void initColors(struct FluidModifierData *mmd = NULL); + void initFireHigh(struct FluidModifierData *mmd = NULL); + void initColorsHigh(struct FluidModifierData *mmd = NULL); + void initLiquid(FluidModifierData *mmd = NULL); + void initLiquidMesh(FluidModifierData *mmd = NULL); + void initObstacle(FluidModifierData *mmd = NULL); + void initGuiding(FluidModifierData *mmd = NULL); + void initFractions(FluidModifierData *mmd = NULL); + void initInVelocity(FluidModifierData *mmd = NULL); + void initOutflow(FluidModifierData *mmd = NULL); + void initSndParts(FluidModifierData *mmd = NULL); + void initLiquidSndParts(FluidModifierData *mmd = NULL); // Pointer transfer: Mantaflow -> Blender void updatePointers(); @@ -414,7 +420,7 @@ struct MANTA { return mPhi; } - static std::atomic<int> solverID; + static atomic<int> solverID; static int with_debug; // on or off (1 or 0), also sets manta debug level // Mesh getters @@ -741,6 +747,8 @@ struct MANTA { size_t mTotalCellsMesh; size_t mTotalCellsParticles; + unordered_map<string, string> mRNAMap; + int mCurrentID; bool mUsingHeat; @@ -852,45 +860,46 @@ struct MANTA { float *mPhi; // Mesh fields - std::vector<Node> *mMeshNodes; - std::vector<Triangle> *mMeshTriangles; - std::vector<pVel> *mMeshVelocities; + vector<Node> *mMeshNodes; + vector<Triangle> *mMeshTriangles; + vector<pVel> *mMeshVelocities; // Particle fields - std::vector<pData> *mFlipParticleData; - std::vector<pVel> *mFlipParticleVelocity; - - std::vector<pData> *mSndParticleData; - std::vector<pVel> *mSndParticleVelocity; - std::vector<float> *mSndParticleLife; - - void initDomain(struct FluidModifierData *mmd); - void initNoise(struct FluidModifierData *mmd); - void initMesh(struct FluidModifierData *mmd); - void initSmoke(struct FluidModifierData *mmd); - void initSmokeNoise(struct FluidModifierData *mmd); + vector<pData> *mFlipParticleData; + vector<pVel> *mFlipParticleVelocity; + + vector<pData> *mSndParticleData; + vector<pVel> *mSndParticleVelocity; + vector<float> *mSndParticleLife; + + void initializeRNAMap(struct FluidModifierData *mmd = NULL); + void initDomain(struct FluidModifierData *mmd = NULL); + void initNoise(struct FluidModifierData *mmd = NULL); + void initMesh(struct FluidModifierData *mmd = NULL); + void initSmoke(struct FluidModifierData *mmd = NULL); + void initSmokeNoise(struct FluidModifierData *mmd = NULL); void initializeMantaflow(); void terminateMantaflow(); - bool runPythonString(std::vector<std::string> commands); - std::string getRealValue(const std::string &varName, FluidModifierData *mmd); - std::string parseLine(const std::string &line, FluidModifierData *mmd); - std::string parseScript(const std::string &setup_string, FluidModifierData *mmd = NULL); - bool updateMeshFromBobj(std::string filename); - bool updateMeshFromObj(std::string filename); - bool updateMeshFromUni(std::string filename); - bool updateParticlesFromUni(std::string filename, bool isSecondarySys, bool isVelData); - bool updateGridFromUni(std::string filename, float *grid, bool isNoise); - bool updateGridFromVDB(std::string filename, float *grid, bool isNoise); - bool updateGridFromRaw(std::string filename, float *grid, bool isNoise); - bool updateMeshFromFile(std::string filename); - bool updateParticlesFromFile(std::string filename, bool isSecondarySys, bool isVelData); - bool updateGridFromFile(std::string filename, float *grid, bool isNoise); - std::string getDirectory(struct FluidModifierData *mmd, std::string subdirectory); - std::string getFile(struct FluidModifierData *mmd, - std::string subdirectory, - std::string fname, - std::string extension, - int framenr); + bool runPythonString(vector<string> commands); + string getRealValue(const string &varName); + string parseLine(const string &line); + string parseScript(const string &setup_string, FluidModifierData *mmd = NULL); + bool updateMeshFromBobj(string filename); + bool updateMeshFromObj(string filename); + bool updateMeshFromUni(string filename); + bool updateParticlesFromUni(string filename, bool isSecondarySys, bool isVelData); + bool updateGridFromUni(string filename, float *grid, bool isNoise); + bool updateGridFromVDB(string filename, float *grid, bool isNoise); + bool updateGridFromRaw(string filename, float *grid, bool isNoise); + bool updateMeshFromFile(string filename); + bool updateParticlesFromFile(string filename, bool isSecondarySys, bool isVelData); + bool updateGridFromFile(string filename, float *grid, bool isNoise); + string getDirectory(struct FluidModifierData *mmd, string subdirectory); + string getFile(struct FluidModifierData *mmd, + string subdirectory, + string fname, + string extension, + int framenr); }; #endif diff --git a/intern/mantaflow/intern/strings/fluid_script.h b/intern/mantaflow/intern/strings/fluid_script.h index dd2111db7d7..c0a23f77d7a 100644 --- a/intern/mantaflow/intern/strings/fluid_script.h +++ b/intern/mantaflow/intern/strings/fluid_script.h @@ -92,7 +92,7 @@ const std::string fluid_variables = mantaMsg('Fluid variables')\n\ dim_s$ID$ = $SOLVER_DIM$\n\ res_s$ID$ = $RES$\n\ -gravity_s$ID$ = vec3($GRAVITY_X$, $GRAVITY_Y$, $GRAVITY_Z$)\n\ +gravity_s$ID$ = vec3($GRAVITY_X$, $GRAVITY_Y$, $GRAVITY_Z$) # in SI unit (e.g. m/s^2)\n\ gs_s$ID$ = vec3($RESX$, $RESY$, $RESZ$)\n\ maxVel_s$ID$ = 0\n\ \n\ @@ -115,6 +115,7 @@ using_speedvectors_s$ID$ = $USING_SPEEDVECTORS$\n\ using_diffusion_s$ID$ = $USING_DIFFUSION$\n\ \n\ # Fluid time params\n\ +timeScale_s$ID$ = $TIME_SCALE$\n\ timeTotal_s$ID$ = $TIME_TOTAL$\n\ timePerFrame_s$ID$ = $TIME_PER_FRAME$\n\ frameLength_s$ID$ = $FRAME_LENGTH$\n\ @@ -132,8 +133,29 @@ end_frame_s$ID$ = $END_FRAME$\n\ domainSize_s$ID$ = $FLUID_DOMAIN_SIZE$ # longest domain side in meters\n\ viscosity_s$ID$ = $FLUID_VISCOSITY$ / (domainSize_s$ID$*domainSize_s$ID$) # kinematic viscosity in m^2/s\n\ \n\ -# Factor to convert blender velocities to manta velocities\n\ -toMantaUnitsFac_s$ID$ = (1.0 / (1.0 / res_s$ID$))\n # = dt/dx * 1/dt "; +# Factors to convert Blender units to Manta units\n\ +ratioMetersToRes_s$ID$ = float(domainSize_s$ID$) / float(res_s$ID$) # [meters / cells]\n\ +mantaMsg('1 Mantaflow cell is ' + str(ratioMetersToRes_s$ID$) + ' Blender length units long.')\n\ +\n\ +ratioResToBLength_s$ID$ = float(res_s$ID$) / float(domainSize_s$ID$) # [cells / blength] (blength: cm, m, or km, ... )\n\ +mantaMsg('1 Blender length unit is ' + str(ratioResToBLength_s$ID$) + ' Mantaflow cells long.')\n\ +\n\ +ratioBTimeToTimstep_s$ID$ = float(1) / float(0.1 * 25 * timeScale_s$ID$) # the time within 1 blender time unit, see also fluid.c\n\ +mantaMsg('1 Blender time unit is ' + str(ratioBTimeToTimstep_s$ID$) + ' Mantaflow time units long.')\n\ +\n\ +ratioFrameToFramelength_s$ID$ = float(1) / float(frameLength_s$ID$) # the time within 1 frame\n\ +mantaMsg('frame / frameLength is ' + str(ratioFrameToFramelength_s$ID$) + ' Mantaflow time units long.')\n\ +\n\ +scaleAcceleration_s$ID$ = ratioResToBLength_s$ID$ * (ratioBTimeToTimstep_s$ID$**2)# [meters/btime^2] to [cells/timestep^2] (btime: sec, min, or h, ...)\n\ +mantaMsg('scaleAcceleration is ' + str(scaleAcceleration_s$ID$))\n\ +\n\ +scaleSpeedFrames_s$ID$ = ratioResToBLength_s$ID$ * ratioFrameToFramelength_s$ID$ # [blength/frame] to [cells/frameLength]\n\ +mantaMsg('scaleSpeed is ' + str(scaleSpeedFrames_s$ID$))\n\ +\n\ +scaleSpeedTime_s$ID$ = ratioResToBLength_s$ID$ * ratioBTimeToTimstep_s$ID$ # [blength/btime] to [cells/frameLength]\n\ +mantaMsg('scaleSpeedTime is ' + str(scaleSpeedTime_s$ID$))\n\ +\n\ +gravity_s$ID$ *= scaleAcceleration_s$ID$ # scale from world acceleration to cell based acceleration\n"; const std::string fluid_variables_noise = "\n\ @@ -342,17 +364,16 @@ def fluid_pre_step_$ID$():\n\ y_obvel_s$ID$.safeDivide(numObs_s$ID$)\n\ z_obvel_s$ID$.safeDivide(numObs_s$ID$)\n\ \n\ - x_obvel_s$ID$.multConst(toMantaUnitsFac_s$ID$)\n\ - y_obvel_s$ID$.multConst(toMantaUnitsFac_s$ID$)\n\ - z_obvel_s$ID$.multConst(toMantaUnitsFac_s$ID$)\n\ - \n\ + x_obvel_s$ID$.multConst(scaleSpeedFrames_s$ID$)\n\ + y_obvel_s$ID$.multConst(scaleSpeedFrames_s$ID$)\n\ + z_obvel_s$ID$.multConst(scaleSpeedFrames_s$ID$)\n\ copyRealToVec3(sourceX=x_obvel_s$ID$, sourceY=y_obvel_s$ID$, sourceZ=z_obvel_s$ID$, target=obvelC_s$ID$)\n\ \n\ # translate invels (world space) to grid space\n\ if using_invel_s$ID$:\n\ - x_invel_s$ID$.multConst(toMantaUnitsFac_s$ID$)\n\ - y_invel_s$ID$.multConst(toMantaUnitsFac_s$ID$)\n\ - z_invel_s$ID$.multConst(toMantaUnitsFac_s$ID$)\n\ + x_invel_s$ID$.multConst(scaleSpeedTime_s$ID$)\n\ + y_invel_s$ID$.multConst(scaleSpeedTime_s$ID$)\n\ + z_invel_s$ID$.multConst(scaleSpeedTime_s$ID$)\n\ copyRealToVec3(sourceX=x_invel_s$ID$, sourceY=y_invel_s$ID$, sourceZ=z_invel_s$ID$, target=invelC_s$ID$)\n\ \n\ if using_guiding_s$ID$:\n\ @@ -362,9 +383,9 @@ def fluid_pre_step_$ID$():\n\ velT_s$ID$.multConst(vec3(gamma_sg$ID$))\n\ \n\ # translate external forces (world space) to grid space\n\ - x_force_s$ID$.multConst(toMantaUnitsFac_s$ID$)\n\ - y_force_s$ID$.multConst(toMantaUnitsFac_s$ID$)\n\ - z_force_s$ID$.multConst(toMantaUnitsFac_s$ID$)\n\ + x_force_s$ID$.multConst(scaleSpeedFrames_s$ID$)\n\ + y_force_s$ID$.multConst(scaleSpeedFrames_s$ID$)\n\ + z_force_s$ID$.multConst(scaleSpeedFrames_s$ID$)\n\ copyRealToVec3(sourceX=x_force_s$ID$, sourceY=y_force_s$ID$, sourceZ=z_force_s$ID$, target=forces_s$ID$)\n\ \n\ # If obstacle has velocity, i.e. is a moving obstacle, switch to dynamic preconditioner\n\ @@ -598,10 +619,9 @@ def bake_guiding_process_$ID$(framenr, format_guiding, path_guiding, resumable): y_guidevel_s$ID$.safeDivide(numGuides_s$ID$)\n\ z_guidevel_s$ID$.safeDivide(numGuides_s$ID$)\n\ \n\ - x_guidevel_s$ID$.multConst(Real(toMantaUnitsFac_s$ID$))\n\ - y_guidevel_s$ID$.multConst(Real(toMantaUnitsFac_s$ID$))\n\ - z_guidevel_s$ID$.multConst(Real(toMantaUnitsFac_s$ID$))\n\ - \n\ + x_guidevel_s$ID$.multConst(scaleSpeedFrames_s$ID$)\n\ + y_guidevel_s$ID$.multConst(scaleSpeedFrames_s$ID$)\n\ + z_guidevel_s$ID$.multConst(scaleSpeedFrames_s$ID$)\n\ copyRealToVec3(sourceX=x_guidevel_s$ID$, sourceY=y_guidevel_s$ID$, sourceZ=z_guidevel_s$ID$, target=guidevelC_s$ID$)\n\ \n\ mantaMsg('Extrapolating guiding velocity')\n\ diff --git a/intern/mantaflow/intern/strings/liquid_script.h b/intern/mantaflow/intern/strings/liquid_script.h index f20b218427c..ee1f0878687 100644 --- a/intern/mantaflow/intern/strings/liquid_script.h +++ b/intern/mantaflow/intern/strings/liquid_script.h @@ -68,7 +68,7 @@ c_s_sp$ID$ = 0.4 # classification constant for snd parts\n\ c_b_sp$ID$ = 0.77 # classification constant for snd parts\n\ pot_radius_sp$ID$ = $SNDPARTICLE_POTENTIAL_RADIUS$\n\ update_radius_sp$ID$ = $SNDPARTICLE_UPDATE_RADIUS$\n\ -scaleFromManta_sp$ID$ = $FLUID_DOMAIN_SIZE$ / float(res_s$ID$) # resize factor for snd parts\n"; +using_snd_pushout_sp$ID$ = $SNDPARTICLE_BOUNDARY_PUSHOUT$\n"; ////////////////////////////////////////////////////////////////////// // GRIDS & MESH & PARTICLESYSTEM @@ -263,7 +263,7 @@ def liquid_step_$ID$():\n\ velOld_s$ID$.copyFrom(vel_s$ID$)\n\ \n\ # forces & pressure solve\n\ - addGravity(flags=flags_s$ID$, vel=vel_s$ID$, gravity=gravity_s$ID$)\n\ + addGravity(flags=flags_s$ID$, vel=vel_s$ID$, gravity=gravity_s$ID$, scale=False)\n\ \n\ mantaMsg('Adding external forces')\n\ addForceField(flags=flags_s$ID$, vel=vel_s$ID$, force=forces_s$ID$)\n\ @@ -371,10 +371,10 @@ def liquid_step_particles_$ID$():\n\ flags_sp$ID$.updateFromLevelset(levelset=phi_sp$ID$)\n\ \n\ # Actual secondary particle simulation\n\ - flipComputeSecondaryParticlePotentials(potTA=trappedAir_sp$ID$, potWC=waveCrest_sp$ID$, potKE=kineticEnergy_sp$ID$, neighborRatio=neighborRatio_sp$ID$, flags=flags_sp$ID$, v=vel_sp$ID$, normal=normal_sp$ID$, phi=phi_sp$ID$, radius=pot_radius_sp$ID$, tauMinTA=tauMin_ta_sp$ID$, tauMaxTA=tauMax_ta_sp$ID$, tauMinWC=tauMin_wc_sp$ID$, tauMaxWC=tauMax_wc_sp$ID$, tauMinKE=tauMin_k_sp$ID$, tauMaxKE=tauMax_k_sp$ID$, scaleFromManta=scaleFromManta_sp$ID$)\n\ + flipComputeSecondaryParticlePotentials(potTA=trappedAir_sp$ID$, potWC=waveCrest_sp$ID$, potKE=kineticEnergy_sp$ID$, neighborRatio=neighborRatio_sp$ID$, flags=flags_sp$ID$, v=vel_sp$ID$, normal=normal_sp$ID$, phi=phi_sp$ID$, radius=pot_radius_sp$ID$, tauMinTA=tauMin_ta_sp$ID$, tauMaxTA=tauMax_ta_sp$ID$, tauMinWC=tauMin_wc_sp$ID$, tauMaxWC=tauMax_wc_sp$ID$, tauMinKE=tauMin_k_sp$ID$, tauMaxKE=tauMax_k_sp$ID$, scaleFromManta=ratioMetersToRes_s$ID$)\n\ flipSampleSecondaryParticles(mode='single', flags=flags_sp$ID$, v=vel_sp$ID$, pts_sec=ppSnd_sp$ID$, v_sec=pVelSnd_pp$ID$, l_sec=pLifeSnd_pp$ID$, lMin=lMin_sp$ID$, lMax=lMax_sp$ID$, potTA=trappedAir_sp$ID$, potWC=waveCrest_sp$ID$, potKE=kineticEnergy_sp$ID$, neighborRatio=neighborRatio_sp$ID$, c_s=c_s_sp$ID$, c_b=c_b_sp$ID$, k_ta=k_ta_sp$ID$, k_wc=k_wc_sp$ID$, dt=sp$ID$.timestep)\n\ flipUpdateSecondaryParticles(mode='linear', pts_sec=ppSnd_sp$ID$, v_sec=pVelSnd_pp$ID$, l_sec=pLifeSnd_pp$ID$, f_sec=pForceSnd_pp$ID$, flags=flags_sp$ID$, v=vel_sp$ID$, neighborRatio=neighborRatio_sp$ID$, radius=update_radius_sp$ID$, gravity=gravity_s$ID$, k_b=k_b_sp$ID$, k_d=k_d_sp$ID$, c_s=c_s_sp$ID$, c_b=c_b_sp$ID$, dt=sp$ID$.timestep)\n\ - if $SNDPARTICLE_BOUNDARY_PUSHOUT$:\n\ + if using_snd_pushout_sp$ID$:\n\ pushOutofObs(parts=ppSnd_sp$ID$, flags=flags_sp$ID$, phiObs=phiObs_sp$ID$, shift=1.0)\n\ flipDeleteParticlesInObstacle(pts=ppSnd_sp$ID$, flags=flags_sp$ID$) # delete particles inside obstacle and outflow cells\n\ \n\ diff --git a/intern/mantaflow/intern/strings/smoke_script.h b/intern/mantaflow/intern/strings/smoke_script.h index fdb58543cec..ea2b1e9d848 100644 --- a/intern/mantaflow/intern/strings/smoke_script.h +++ b/intern/mantaflow/intern/strings/smoke_script.h @@ -376,9 +376,9 @@ def smoke_step_$ID$():\n\ \n\ if using_heat_s$ID$:\n\ mantaMsg('Adding heat buoyancy')\n\ - addBuoyancy(flags=flags_s$ID$, density=heat_s$ID$, vel=vel_s$ID$, gravity=gravity_s$ID$, coefficient=buoyancy_heat_s$ID$)\n\ + addBuoyancy(flags=flags_s$ID$, density=heat_s$ID$, vel=vel_s$ID$, gravity=gravity_s$ID$, coefficient=buoyancy_heat_s$ID$, scale=False)\n\ mantaMsg('Adding buoyancy')\n\ - addBuoyancy(flags=flags_s$ID$, density=density_s$ID$, vel=vel_s$ID$, gravity=gravity_s$ID$, coefficient=buoyancy_dens_s$ID$)\n\ + addBuoyancy(flags=flags_s$ID$, density=density_s$ID$, vel=vel_s$ID$, gravity=gravity_s$ID$, coefficient=buoyancy_dens_s$ID$, scale=False)\n\ \n\ mantaMsg('Adding forces')\n\ addForceField(flags=flags_s$ID$, vel=vel_s$ID$, force=forces_s$ID$)\n\ diff --git a/intern/string/CMakeLists.txt b/intern/string/CMakeLists.txt deleted file mode 100644 index 8c400f320ae..00000000000 --- a/intern/string/CMakeLists.txt +++ /dev/null @@ -1,38 +0,0 @@ -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software Foundation, -# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# The Original Code is Copyright (C) 2006, Blender Foundation -# All rights reserved. -# ***** END GPL LICENSE BLOCK ***** - -set(INC - . -) - -set(INC_SYS - -) - -set(SRC - intern/STR_String.cpp - - STR_String.h -) - -set(LIB -) - -blender_add_lib(bf_intern_string "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/intern/string/STR_String.h b/intern/string/STR_String.h deleted file mode 100644 index 97b23345f91..00000000000 --- a/intern/string/STR_String.h +++ /dev/null @@ -1,366 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - */ - -/** \file - * \ingroup string - */ - -#ifndef __STR_STRING_H__ -#define __STR_STRING_H__ - -#ifndef STR_NO_ASSERTD -# undef assertd -# define assertd(exp) ((void)NULL) -#endif - -#include <limits.h> -#include <vector> - -#include <cstdlib> -#include <cstring> - -#ifdef WITH_CXX_GUARDEDALLOC -# include "MEM_guardedalloc.h" -#endif - -#ifdef _WIN32 -# define stricmp _stricmp -#endif - -class STR_String; - -typedef unsigned long dword; -typedef const STR_String &rcSTR_String; -typedef unsigned char byte; - -/** - * Smart String Value class. Is used by parser when an expression tree is build containing string. - */ - -class STR_String { - public: - // Initialization - STR_String(); - STR_String(char c); - STR_String(char c, int len); - STR_String(const char *str); - STR_String(const char *str, int len); - STR_String(const STR_String &str); - STR_String(const STR_String &str, int len); - STR_String(const char *src1, int src1_len, const char *src2, int src2_len); - explicit STR_String(int val); - explicit STR_String(dword val); - explicit STR_String(float val); - explicit STR_String(double val); - inline ~STR_String() - { - delete[] this->m_data; - } - - // Operations - STR_String &Format(const char *fmt, ...) // Set formatted text to string -#ifdef __GNUC__ - __attribute__((format(printf, 2, 3))) -#endif - ; - STR_String &FormatAdd(const char *fmt, ...) // Add formatted text to string -#ifdef __GNUC__ - __attribute__((format(printf, 2, 3))) -#endif - ; - inline void Clear() - { - this->m_len = this->m_data[0] = 0; - } - inline const STR_String &Reverse() - { - for (int i1 = 0, i2 = this->m_len - 1; i1 < i2; i1++, i2--) { - std::swap(this->m_data[i1], this->m_data[i2]); - } - return *this; - } - - // Properties - bool IsUpper() const; - bool IsLower() const; - inline bool IsEmpty() const - { - return this->m_len == 0; - } - inline int Length() const - { - return this->m_len; - } - - // Data access - inline STR_String &SetLength(int len) - { - AllocBuffer(len, true); - this->m_len = len; - this->m_data[len] = 0; - return *this; - } - inline char GetAt(int pos) const - { - assertd(pos < this->m_len); - return this->m_data[pos]; - } - inline void SetAt(int pos, char c) - { - assertd(pos < this->m_len); - this->m_data[pos] = c; - } - inline void SetAt(int pos, rcSTR_String str); - inline void SetAt(int pos, int num, rcSTR_String str); - void Replace(int pos, rcSTR_String str); - void Replace(int pos, int num, rcSTR_String str); - - // Substrings - inline STR_String Left(int num) const - { - num = (num < this->m_len ? num : this->m_len); - return STR_String(this->m_data, num); - } - inline STR_String Right(int num) const - { - num = (num < this->m_len ? num : this->m_len); - return STR_String(this->m_data + this->m_len - num, num); - } - inline STR_String Mid(int pos, int num = INT_MAX) const - { - pos = (pos < this->m_len ? pos : this->m_len); - num = (num < (this->m_len - pos) ? num : (this->m_len - pos)); - return STR_String(this->m_data + pos, num); - } - - // Comparison - int Compare(rcSTR_String rhs) const; - int CompareNoCase(rcSTR_String rhs) const; - inline bool IsEqual(rcSTR_String rhs) const - { - return (Compare(rhs) == 0); - } - inline bool IsEqualNoCase(rcSTR_String rhs) const - { - return (CompareNoCase(rhs) == 0); - } - - // Search/replace - int Find(char c, int pos = 0) const; - int Find(const char *str, int pos = 0) const; - int Find(rcSTR_String str, int pos = 0) const; - int RFind(char c) const; - int FindOneOf(const char *set, int pos = 0) const; - int RFindOneOf(const char *set, int pos = 0) const; - - std::vector<STR_String> Explode(char c) const; - - // Formatting - STR_String &Upper(); - STR_String &Lower(); - STR_String &Capitalize(); - STR_String &TrimLeft(); - STR_String &TrimLeft(char *set); - STR_String &TrimRight(); - STR_String &TrimRight(char *set); - STR_String &Trim(); - STR_String &Trim(char *set); - STR_String &TrimQuotes(); - - // Conversions - // inline operator char*() { return this->m_data; } - inline operator const char *() const - { - return this->m_data; - } - inline char *Ptr() - { - return this->m_data; - } - inline const char *ReadPtr() const - { - return this->m_data; - } - inline float ToFloat() const - { - float x = (float)(atof(this->m_data)); - return x; - } - inline int ToInt() const - { - return atoi(this->m_data); - } - - // Operators - inline rcSTR_String operator=(const byte *rhs) - { - return Copy((const char *)rhs, strlen((const char *)rhs)); - } - inline rcSTR_String operator=(rcSTR_String rhs) - { - return Copy(rhs.ReadPtr(), rhs.Length()); - } - inline rcSTR_String operator=(char rhs) - { - return Copy(&rhs, 1); - } - inline rcSTR_String operator=(const char *rhs) - { - return Copy(rhs, strlen(rhs)); - } - - inline rcSTR_String operator+=(const char *rhs) - { - return Concat(rhs, strlen(rhs)); - } - inline rcSTR_String operator+=(rcSTR_String rhs) - { - return Concat(rhs.ReadPtr(), rhs.Length()); - } - inline rcSTR_String operator+=(char rhs) - { - return Concat(&rhs, 1); - } - - inline friend bool operator<(rcSTR_String lhs, rcSTR_String rhs) - { - return (strcmp(lhs, rhs) < 0); - } - inline friend bool operator<(rcSTR_String lhs, const char *rhs) - { - return (strcmp(lhs, rhs) < 0); - } - inline friend bool operator<(const char *lhs, rcSTR_String rhs) - { - return (strcmp(lhs, rhs) < 0); - } - inline friend bool operator>(rcSTR_String lhs, rcSTR_String rhs) - { - return (strcmp(lhs, rhs) > 0); - } - inline friend bool operator>(rcSTR_String lhs, const char *rhs) - { - return (strcmp(lhs, rhs) > 0); - } - inline friend bool operator>(const char *lhs, rcSTR_String rhs) - { - return (strcmp(lhs, rhs) > 0); - } - inline friend bool operator<=(rcSTR_String lhs, rcSTR_String rhs) - { - return (strcmp(lhs, rhs) <= 0); - } - inline friend bool operator<=(rcSTR_String lhs, const char *rhs) - { - return (strcmp(lhs, rhs) <= 0); - } - inline friend bool operator<=(const char *lhs, rcSTR_String rhs) - { - return (strcmp(lhs, rhs) <= 0); - } - inline friend bool operator>=(rcSTR_String lhs, rcSTR_String rhs) - { - return (strcmp(lhs, rhs) >= 0); - } - inline friend bool operator>=(rcSTR_String lhs, const char *rhs) - { - return (strcmp(lhs, rhs) >= 0); - } - inline friend bool operator>=(const char *lhs, rcSTR_String rhs) - { - return (strcmp(lhs, rhs) >= 0); - } - inline friend bool operator==(rcSTR_String lhs, rcSTR_String rhs) - { - return ((lhs.Length() == rhs.Length()) && (memcmp(lhs, rhs, lhs.Length()) == 0)); - } - inline friend bool operator==(rcSTR_String lhs, const char *rhs) - { - return (strncmp(lhs, rhs, lhs.Length() + 1) == 0); - } - inline friend bool operator==(const char *lhs, rcSTR_String rhs) - { - return (strncmp(lhs, rhs, rhs.Length() + 1) == 0); - } - inline friend bool operator!=(rcSTR_String lhs, rcSTR_String rhs) - { - return ((lhs.Length() != rhs.Length()) || (memcmp(lhs, rhs, lhs.Length()) != 0)); - } - inline friend bool operator!=(rcSTR_String lhs, const char *rhs) - { - return (strncmp(lhs, rhs, lhs.Length() + 1) != 0); - } - inline friend bool operator!=(const char *lhs, rcSTR_String rhs) - { - return (strncmp(lhs, rhs, rhs.Length() + 1) != 0); - } - - // serializing - // int Serialize(pCStream stream); - - protected: - // Implementation - void AllocBuffer(int len, bool keep_contents); - rcSTR_String Copy(const char *src, int len); - rcSTR_String Concat(const char *data, int len); - - static bool isLower(char c) - { - return !isUpper(c); - } - static bool isUpper(char c) - { - return (c >= 'A') && (c <= 'Z'); - } - static bool isSpace(char c) - { - return (c == ' ') || (c == '\t'); - } - - char *m_data; // -> STR_String data - int m_len; // z Data length - int m_max; // Space in data buffer - -#ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("CXX:STR_String") -#endif -}; - -inline STR_String operator+(rcSTR_String lhs, rcSTR_String rhs) -{ - return STR_String(lhs.ReadPtr(), lhs.Length(), rhs.ReadPtr(), rhs.Length()); -} -inline STR_String operator+(rcSTR_String lhs, char rhs) -{ - return STR_String(lhs.ReadPtr(), lhs.Length(), &rhs, 1); -} -inline STR_String operator+(char lhs, rcSTR_String rhs) -{ - return STR_String(&lhs, 1, rhs.ReadPtr(), rhs.Length()); -} -inline STR_String operator+(rcSTR_String lhs, const char *rhs) -{ - return STR_String(lhs.ReadPtr(), lhs.Length(), rhs, strlen(rhs)); -} -inline STR_String operator+(const char *lhs, rcSTR_String rhs) -{ - return STR_String(lhs, strlen(lhs), rhs.ReadPtr(), rhs.Length()); -} - -#endif //__STR_STRING_H__ diff --git a/intern/string/intern/STR_String.cpp b/intern/string/intern/STR_String.cpp deleted file mode 100644 index 306e786969b..00000000000 --- a/intern/string/intern/STR_String.cpp +++ /dev/null @@ -1,637 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - */ - -/** \file - * \ingroup string - * - * Copyright (C) 2001 NaN Technologies B.V. - * This file was formerly known as: GEN_StdString.cpp. - */ - -#include "STR_String.h" -#include <ctype.h> -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -/*------------------------------------------------------------------------------------------------- - Construction / destruction --------------------------------------------------------------------------------------------------*/ - -#define STR_STRING_SIZE_DEFAULT_WORD 32 /* default size for a new word */ -#define STR_STRING_SIZE_DEFAULT_CHAR 9 /* default size for a new char */ - -// -// Construct an empty string -// -STR_String::STR_String() - : m_data(new char[STR_STRING_SIZE_DEFAULT_WORD]), m_len(0), m_max(STR_STRING_SIZE_DEFAULT_WORD) -{ - this->m_data[0] = 0; -} - -// -// Construct a string of one character -// -STR_String::STR_String(char c) - : m_data(new char[STR_STRING_SIZE_DEFAULT_CHAR]), m_len(1), m_max(STR_STRING_SIZE_DEFAULT_CHAR) -{ - this->m_data[0] = c; - this->m_data[1] = 0; -} - -// -// Construct a string of multiple repeating characters -// -STR_String::STR_String(char c, int len) : m_data(new char[len + 8]), m_len(len), m_max(len + 8) -{ - assertd(this->m_data != NULL); - memset(this->m_data, c, len); - this->m_data[len] = 0; -} - -// -// Construct a string from a pointer-to-ASCIIZ-string -// -// MAART: Changed to test for null strings -STR_String::STR_String(const char *str) -{ - if (str) { - this->m_len = ::strlen(str); - this->m_max = this->m_len + 8; - this->m_data = new char[this->m_max]; - assertd(this->m_data != NULL); - ::memcpy(this->m_data, str, this->m_len); - this->m_data[this->m_len] = 0; - } - else { - this->m_data = NULL; - this->m_len = 0; - this->m_max = 8; - } -} - -// -// Construct a string from a pointer-to-ASCII-string and a length -// -STR_String::STR_String(const char *str, int len) - : m_data(new char[len + 8]), m_len(len), m_max(len + 8) -{ - assertd(this->m_data != NULL); - memcpy(this->m_data, str, len); - this->m_data[len] = 0; -} - -// -// Construct a string from another string -// -STR_String::STR_String(rcSTR_String str) - : m_data(new char[str.Length() + 8]), m_len(str.Length()), m_max(str.Length() + 8) -{ - assertd(this->m_data != NULL); - assertd(str.this->m_data != NULL); - memcpy(this->m_data, str.ReadPtr(), str.Length()); - this->m_data[str.Length()] = 0; -} - -// -// Construct a string from the first number of characters in another string -// -STR_String::STR_String(rcSTR_String str, int len) - : m_data(new char[len + 8]), m_len(len), m_max(len + 8) -{ - assertd(this->m_data != NULL); - assertd(str.this->m_data != NULL); - memcpy(this->m_data, str.ReadPtr(), str.Length()); - this->m_data[str.Length()] = 0; -} - -// -// Create a string by concatenating two sources -// -STR_String::STR_String(const char *src1, int len1, const char *src2, int len2) - : m_data(new char[len1 + len2 + 8]), m_len(len1 + len2), m_max(len1 + len2 + 8) -{ - assertd(this->m_data != NULL); - memcpy(this->m_data, src1, len1); - memcpy(this->m_data + len1, src2, len2); - this->m_data[len1 + len2] = 0; -} - -// -// Create a string with an integer value -// -STR_String::STR_String(int val) - : m_data(new char[STR_STRING_SIZE_DEFAULT_WORD]), m_max(STR_STRING_SIZE_DEFAULT_WORD) -{ - assertd(this->m_data != NULL); - this->m_len = sprintf(this->m_data, "%d", val); -} - -// -// Create a string with a dword value -// -STR_String::STR_String(dword val) - : m_data(new char[STR_STRING_SIZE_DEFAULT_WORD]), m_max(STR_STRING_SIZE_DEFAULT_WORD) -{ - assertd(this->m_data != NULL); - this->m_len = sprintf(this->m_data, "%lu", val); -} - -// -// Create a string with a floating point value -// -STR_String::STR_String(float val) - : m_data(new char[STR_STRING_SIZE_DEFAULT_WORD]), m_max(STR_STRING_SIZE_DEFAULT_WORD) -{ - assertd(this->m_data != NULL); - this->m_len = sprintf(this->m_data, "%g", val); -} - -// -// Create a string with a double value -// -STR_String::STR_String(double val) - : m_data(new char[STR_STRING_SIZE_DEFAULT_WORD]), m_max(STR_STRING_SIZE_DEFAULT_WORD) -{ - assertd(this->m_data != NULL); - this->m_len = sprintf(this->m_data, "%g", val); -} - -/*------------------------------------------------------------------------------------------------- - Buffer management --------------------------------------------------------------------------------------------------*/ - -// -// Make sure that the allocated buffer is at least <len> in size -// -void STR_String::AllocBuffer(int len, bool keep_contents) -{ - // Check if we have enough space - if (len + 1 <= this->m_max) - return; - - // Reallocate string - char *new_data = new char[len + 8]; - if (keep_contents) { - memcpy(new_data, this->m_data, this->m_len); - } - delete[] this->m_data; - - // Accept new data - this->m_max = len + 8; - this->m_data = new_data; - assertd(this->m_data != NULL); -} - -/*------------------------------------------------------------------------------------------------- - Basic string operations --------------------------------------------------------------------------------------------------*/ - -// -// Format string (as does sprintf) -// -STR_String &STR_String::Format(const char *fmt, ...) -{ - AllocBuffer(2048, false); - - assertd(this->m_data != NULL); - // Expand arguments and format to string - va_list args; - va_start(args, fmt); - this->m_len = vsprintf(this->m_data, fmt, args); - assertd(this->m_len <= 2048); - va_end(args); - - return *this; -} - -// -// Format string (as does sprintf) -// -STR_String &STR_String::FormatAdd(const char *fmt, ...) -{ - AllocBuffer(2048, false); - - assertd(this->m_data != NULL); - // Expand arguments and format to string - va_list args; - va_start(args, fmt); - this->m_len += vsprintf(this->m_data + this->m_len, fmt, args); - assertd(this->m_len <= 2048); - va_end(args); - - return *this; -} - -/*------------------------------------------------------------------------------------------------- - Properties --------------------------------------------------------------------------------------------------*/ - -// -// Check if string is entirely in UPPERCase -// -bool STR_String::IsUpper() const -{ - for (int i = 0; i < this->m_len; i++) - if (isLower(this->m_data[i])) - return false; - - return true; -} - -// -// Check if string is entirely in lowerCase -// -bool STR_String::IsLower() const -{ - for (int i = 0; i < this->m_len; i++) - if (isUpper(this->m_data[i])) - return false; - - return true; -} - -/*------------------------------------------------------------------------------------------------- - Search/Replace --------------------------------------------------------------------------------------------------*/ - -// -// Find the first orccurence of <c> in the string -// -int STR_String::Find(char c, int pos) const -{ - assertd(pos >= 0); - assertd(this->m_len == 0 || pos < this->m_len); - assertd(this->m_data != NULL); - char *find_pos = strchr(this->m_data + pos, c); - return (find_pos) ? (find_pos - this->m_data) : -1; -} - -// -// Find the first occurrence of <str> in the string -// -int STR_String::Find(const char *str, int pos) const -{ - assertd(pos >= 0); - assertd(this->m_len == 0 || pos < this->m_len); - assertd(this->m_data != NULL); - char *find_pos = strstr(this->m_data + pos, str); - return (find_pos) ? (find_pos - this->m_data) : -1; -} - -// -// Find the first occurrence of <str> in the string -// -int STR_String::Find(rcSTR_String str, int pos) const -{ - assertd(pos >= 0); - assertd(this->m_len == 0 || pos < this->m_len); - assertd(this->m_data != NULL); - char *find_pos = strstr(this->m_data + pos, str.ReadPtr()); - return (find_pos) ? (find_pos - this->m_data) : -1; -} - -// -// Find the last occurrence of <c> in the string -// -int STR_String::RFind(char c) const -{ - assertd(this->m_data != NULL); - char *pos = strrchr(this->m_data, c); - return (pos) ? (pos - this->m_data) : -1; -} - -// -// Find the first occurrence of any character in character set <set> in the string -// -int STR_String::FindOneOf(const char *set, int pos) const -{ - assertd(pos >= 0); - assertd(this->m_len == 0 || pos < this->m_len); - assertd(this->m_data != NULL); - char *find_pos = strpbrk(this->m_data + pos, set); - return (find_pos) ? (find_pos - this->m_data) : -1; -} - -// -// Replace a character in this string with another string -// -void STR_String::Replace(int pos, rcSTR_String str) -{ - // bounds(pos, 0, Length()-1); - - if (str.Length() < 1) { - // Remove one character from the string - memcpy(this->m_data + pos, this->m_data + pos + 1, this->m_len - pos); - } - else { - // Insert zero or more characters into the string - AllocBuffer(this->m_len + str.Length() - 1, true); - if (str.Length() != 1) - memcpy(this->m_data + pos + str.Length(), this->m_data + pos + 1, Length() - pos); - memcpy(this->m_data + pos, str.ReadPtr(), str.Length()); - } - - this->m_len += str.Length() - 1; -} - -// -// Replace a substring of this string with another string -// -void STR_String::Replace(int pos, int num, rcSTR_String str) -{ - // bounds(pos, 0, Length()-1); - // bounds(pos+num, 0, Length()); - assertd(num >= 1); - - if (str.Length() < num) { - // Remove some data from the string by replacement - memcpy( - this->m_data + pos + str.Length(), this->m_data + pos + num, this->m_len - pos - num + 1); - memcpy(this->m_data + pos, str.ReadPtr(), str.Length()); - } - else { - // Insert zero or more characters into the string - AllocBuffer(this->m_len + str.Length() - num, true); - if (str.Length() != num) - memcpy( - this->m_data + pos + str.Length(), this->m_data + pos + num, Length() - pos - num + 1); - memcpy(this->m_data + pos, str.ReadPtr(), str.Length()); - } - - this->m_len += str.Length() - num; -} - -/*------------------------------------------------------------------------------------------------- - Comparison --------------------------------------------------------------------------------------------------*/ - -// -// Compare two strings and return the result, -// <0 if *this<rhs, >0 if *this>rhs or 0 if *this==rhs -// -int STR_String::Compare(rcSTR_String rhs) const -{ - return strcmp(this->ReadPtr(), rhs.ReadPtr()); -} - -// -// Compare two strings without respecting case and return the result, -// <0 if *this<rhs, >0 if *this>rhs or 0 if *this==rhs -// -int STR_String::CompareNoCase(rcSTR_String rhs) const -{ -#ifdef WIN32 - return stricmp(this->ReadPtr(), rhs.ReadPtr()); -#else - return strcasecmp(this->ReadPtr(), rhs.ReadPtr()); -#endif -} - -/*------------------------------------------------------------------------------------------------- - Formatting --------------------------------------------------------------------------------------------------*/ - -// -// Capitalize string, "heLLo" -> "HELLO" -// -STR_String &STR_String::Upper() -{ - assertd(this->m_data != NULL); -#ifdef WIN32 - _strupr(this->m_data); -#else - for (int i = 0; i < this->m_len; i++) - this->m_data[i] = (this->m_data[i] >= 'a' && this->m_data[i] <= 'z') ? - this->m_data[i] + 'A' - 'a' : - this->m_data[i]; -#endif - return *this; -} - -// -// Lower string, "heLLo" -> "hello" -// -STR_String &STR_String::Lower() -{ - assertd(this->m_data != NULL); -#ifdef WIN32 - _strlwr(this->m_data); -#else - for (int i = 0; i < this->m_len; i++) - this->m_data[i] = (this->m_data[i] >= 'A' && this->m_data[i] <= 'Z') ? - this->m_data[i] + 'a' - 'A' : - this->m_data[i]; -#endif - return *this; -} - -// -// Capitalize string, "heLLo" -> "Hello" -// -STR_String &STR_String::Capitalize() -{ - assertd(this->m_data != NULL); -#ifdef WIN32 - if (this->m_len > 0) - this->m_data[0] = toupper(this->m_data[0]); - if (this->m_len > 1) - _strlwr(this->m_data + 1); -#else - if (this->m_len > 0) - this->m_data[0] = (this->m_data[0] >= 'a' && this->m_data[0] <= 'z') ? - this->m_data[0] + 'A' - 'a' : - this->m_data[0]; - for (int i = 1; i < this->m_len; i++) - this->m_data[i] = (this->m_data[i] >= 'A' && this->m_data[i] <= 'Z') ? - this->m_data[i] + 'a' - 'A' : - this->m_data[i]; -#endif - return *this; -} - -// -// Trim whitespace from the left side of the string -// -STR_String &STR_String::TrimLeft() -{ - int skip; - assertd(this->m_data != NULL); - for (skip = 0; isSpace(this->m_data[skip]); skip++, this->m_len--) { - /* pass */ - } - memmove(this->m_data, this->m_data + skip, this->m_len + 1); - return *this; -} - -// -// Trim whitespaces from the right side of the string -// -STR_String &STR_String::TrimRight() -{ - assertd(this->m_data != NULL); - while (this->m_len && isSpace(this->m_data[this->m_len - 1])) - this->m_len--; - this->m_data[this->m_len] = 0; - return *this; -} - -// -// Trim spaces from both sides of the character set -// -STR_String &STR_String::Trim() -{ - TrimRight(); - TrimLeft(); - return *this; -} - -// -// Trim characters from the character set <set> from the left side of the string -// -STR_String &STR_String::TrimLeft(char *set) -{ - int skip; - assertd(this->m_data != NULL); - for (skip = 0; this->m_len && strchr(set, this->m_data[skip]); skip++, this->m_len--) { - /* pass */ - } - memmove(this->m_data, this->m_data + skip, this->m_len + 1); - return *this; -} - -// -// Trim characters from the character set <set> from the right side of the string -// -STR_String &STR_String::TrimRight(char *set) -{ - assertd(this->m_data != NULL); - while (this->m_len && strchr(set, this->m_data[this->m_len - 1])) - this->m_len--; - this->m_data[this->m_len] = 0; - return *this; -} - -// -// Trim characters from the character set <set> from both sides of the character set -// -STR_String &STR_String::Trim(char *set) -{ - TrimRight(set); - TrimLeft(set); - return *this; -} - -// -// Trim quotes from both sides of the string -// -STR_String &STR_String::TrimQuotes() -{ - // Trim quotes if they are on both sides of the string - assertd(this->m_data != NULL); - if ((this->m_len >= 2) && (this->m_data[0] == '\"') && (this->m_data[this->m_len - 1] == '\"')) { - memmove(this->m_data, this->m_data + 1, this->m_len - 2 + 1); - this->m_len -= 2; - } - return *this; -} - -/*------------------------------------------------------------------------------------------------- - Assignment/Concatenation --------------------------------------------------------------------------------------------------*/ - -// -// Set the string's conents to a copy of <src> with length <len> -// -rcSTR_String STR_String::Copy(const char *src, int len) -{ - assertd(len >= 0); - assertd(src); - assertd(this->m_data != NULL); - - AllocBuffer(len, false); - this->m_len = len; - memcpy(this->m_data, src, len); - this->m_data[this->m_len] = 0; - - return *this; -} - -// -// Concate a number of bytes to the current string -// -rcSTR_String STR_String::Concat(const char *data, int len) -{ - assertd(this->m_len >= 0); - assertd(len >= 0); - assertd(data); - assertd(this->m_data != NULL); - - AllocBuffer(this->m_len + len, true); - memcpy(this->m_data + this->m_len, data, len); - this->m_len += len; - this->m_data[this->m_len] = 0; - - return *this; -} - -std::vector<STR_String> STR_String::Explode(char c) const -{ - STR_String lcv = *this; - std::vector<STR_String> uc; - - while (lcv.Length()) { - int pos = lcv.Find(c); - if (pos < 0) { - uc.push_back(lcv); - lcv.Clear(); - } - else { - uc.push_back(lcv.Left(pos)); - lcv = lcv.Mid(pos + 1); - } - } - - // uc. -= STR_String(""); - - return uc; -} - -#if 0 - -int STR_String::Serialize(pCStream stream) -{ - if (stream->GetAccess() == CStream::Access_Read) { - int ln; - stream->Read(&ln, sizeof(ln)); - AllocBuffer(ln, false); - stream->Read(this->m_data, ln); - this->m_data[ln] = '\0'; - this->m_len = ln; - } - else { - stream->Write(&this->m_len, sizeof(this->m_len)); - stream->Write(this->m_data, this->m_len); - } - - return this->m_len + sizeof(this->m_len); -} -#endif |