Add Chromium-only Blender WebEngine parity work

This commit is contained in:
mes123456
2026-08-12 04:47:48 -04:00
commit 9fd26010f6
18225 changed files with 11622124 additions and 0 deletions

View File

@@ -0,0 +1,106 @@
/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editorui
*/
#pragma once
#include "GPU_shader_builtin.hh"
#include "GPU_texture.hh"
namespace blender {
struct rcti;
struct ColorManagedDisplaySettings;
struct ColorManagedViewSettings;
struct ImBuf;
struct bContext;
namespace gpu {
class Shader;
} // namespace gpu
/**
* Utility to render a quad using pixel bitmap
* data in system memory.
*/
class PixelBitmapDrawer {
gpu::Shader *shader;
unsigned int pos;
unsigned int texco;
public:
/**
* Prepares for drawing, using one of built-in shaders
* (e.g. GPU_SHADER_3D_IMAGE_COLOR).
*
* Before drawing additional uniforms can be set on the shader.
*/
PixelBitmapDrawer(GPUBuiltinShader builtin_shader);
/**
* Prepares for drawing, with shader set up by the caller.
* The shader is expected to use `pos` and `texCoord` attributes,
* and `image` texture.
*/
PixelBitmapDrawer();
gpu::Shader *shader_get()
{
return shader;
}
/**
* Draws pixel data on a rectangle.
*
* The model-view and projection matrices are assumed to define a 1-to-1 mapping to screen space.
*
* If color is null, white is used.
*/
void draw(float x,
float y,
int img_w,
int img_h,
gpu::TextureFormat gpu_format,
bool use_filter,
const void *rect,
float scale_x,
float scale_y,
const float color[4]);
private:
void init_vertex_attributes();
};
/**
* Draw the image buffer, with the given display transform parameters.
*/
void ED_draw_imbuf(const ImBuf *ibuf,
float x,
float y,
bool use_filter,
const ColorManagedViewSettings *view_settings,
const ColorManagedDisplaySettings *display_settings,
float zoom_x,
float zoom_y);
/**
* Draw the image buffer, using display transform parameters from the context.
*/
void ED_draw_imbuf_ctx(const bContext *C,
const ImBuf *ibuf,
float x,
float y,
bool use_filter,
float zoom_x,
float zoom_y);
/**
* Don't move to `GPU_immediate_util.hh`
* because this uses user-preferences and isn't very low level.
*/
void immDrawBorderCorners(unsigned int pos, const rcti *border, float zoomx, float zoomy);
} // namespace blender

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,205 @@
/* SPDX-FileCopyrightText: 2026 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edanimation
*
* \brief Defines an abstraction around various structs to modify their transform properties via a
* unified API for the purpose of animation.
*/
#pragma once
#include "BLI_array.hh"
#include "BLI_span.hh"
#include "DNA_action_types.h"
#include "RNA_types.hh"
namespace blender {
struct bPoseChannel;
struct ID;
namespace ed {
/**
* Used to limit the modification of properties to certain axes.
*/
enum AxisMutable : int8_t {
AXIS_MUTABLE_X = 1 << 0,
AXIS_MUTABLE_Y = 1 << 1,
AXIS_MUTABLE_Z = 1 << 2,
AXIS_MUTABLE_ALL = AXIS_MUTABLE_X | AXIS_MUTABLE_Y | AXIS_MUTABLE_Z,
/* There is currently no support for a W axis. This was already the case when porting this enum
* from the pose slide code. */
};
ENUM_OPERATORS(AxisMutable);
/* By using Array<float, 4> we enforce a stack allocation limit of 4. Since we use at most 4
* elements per property, we ensure that the values are always on the stack
* for better performance. */
using TransformFloats = Array<float, 4>;
using TransformFloatPtrs = Array<float *, 4>;
/**
* Describes a rotation in a specific mode and can be used to convert into other modes.
*/
struct Rotation {
/* The array size differs depending on the rotation mode. */
TransformFloats values;
eRotationModes mode;
/**
* Returns a copy of the rotation in the given mode.
*/
Rotation converted_to_mode(eRotationModes mode) const;
};
/**
* Provides a common interface to transform values for multiple structs.
* In a way this is similar to RNA, however RNA has the issue that the properties don't have
* consistent naming making it impossible to work with them in a generic way.
*/
class AnimTransformable {
public:
enum class Type : int8_t {
POSE_BONE,
OBJECT,
};
enum class PropertyType : int8_t { LOCATION, ROTATION, SCALE };
private:
Type type_;
ID *owner_id_;
/* The struct wrapped by the AnimTransformable. For possible types see `Type`. */
void *data_;
/* This is the path from the owner ID to the struct that the AnimTransformable represents. Has to
* be created in the constructor. For structs that are an ID this is an empty string. */
std::string rna_path_from_id_;
/* We are assuming here that the ground truth of transforms is store in separate loc rot scale
* and not in a matrix, thus skew is not supported. */
MutableSpan<float> location_;
/* Rotation can be expressed in different modes, which are stored in separate arrays. We have to
* use an Array of float* because the angle of axis-angle is a separate float property. This is
* in contrast to e.g. `location_` which is always a float array so it can be referenced with a
* `MutableSpan`. For the order of elements, see `RotationModeIndices` in `transformable.cc`. */
Array<TransformFloatPtrs> rotations_;
/* Points to an enum with the current rotation mode. See `eRotationModes`. */
eRotationModes *rotation_mode_;
MutableSpan<float> scale_;
/**
* Returns the correct array based on the given mode. Asserts that the array is set for the
* current transformable.
*/
const TransformFloatPtrs *get_rotation_array_from_mode(eRotationModes mode) const;
public:
/* There has to be a constructor for every struct supported. */
/* Constructor for pose bones. */
AnimTransformable(Object &owner_id, bPoseChannel &pchan);
/* Constructor for Objects. */
explicit AnimTransformable(Object &object);
Type type() const
{
return type_;
}
ID *owner_id() const
{
return owner_id_;
}
template<typename T> T data() const;
/* Returns the rna path from the ID to the struct represented by this transformable. If the
* struct is an ID this is an empty string. */
StringRefNull rna_path() const;
/**
* Returns a string to the given property type.
*/
std::string rna_path_to_property(PropertyType prop_type) const;
/**
* Returns a copy of the rotation in the mode the transformable is currently in.
*/
Rotation get_rotation() const;
/**
* Sets the rotation for the mode the transformable is currently in. If that doesn't match with
* the given rotation, the `value` is converted.
*/
void set_rotation(const Rotation &value);
/**
* Returns the current rotation mode of the transformable.
*/
eRotationModes get_rotation_mode() const;
/**
* Blends the rotation to the given `target`. If the rotation mode of the transformable and that
* of the `target` does not match, the `target` is converted. This uses the correct interpolation
* math depending on the rotation mode (LERP for euler, SLERP for quaternion). At `factor` 0, the
* current rotation remains unchanged.
*/
void blend_rotation_to(const Rotation &target, float factor, AxisMutable axis_flag);
/**
* Returns a copy of the property values for the given property type.
* While this will return the values of the current rotation mode for PropertyType::ROTATION, it
* is best to use the explicit function for it so a `Rotation` struct is returned which has more
* features for dealing with different rotation modes.
*/
TransformFloats get_property(PropertyType prop_type) const;
/**
* Generic way to set the given transform property. It is asserted that the value count matches
* the current rotation mode. Use `set_rotation` to automatically convert to the correct mode.
*/
void set_property(PropertyType prop_type, Span<float> values, AxisMutable axis_flag);
/**
* Do a linear blend of the property values towards the given `target`. It is asserted that the
* given span size equals the property size. When setting the rotation property, it is the
* responsibility of the caller to ensure that the values are in the correct mode. It is assumed
* the `target` is in the same rotation mode as the transformable.
*
* \note This will not work correctly for quaternion rotations. Use `blend_rotation_to` instead.
*/
void blend_property_to(PropertyType prop_type,
Span<float> target,
float factor,
AxisMutable axis_flag);
/**
* Overloaded function that blends all values of the given property type to the same float.
*/
void blend_property_to(PropertyType prop_type,
float target,
float factor,
AxisMutable axis_flag);
};
/**
* Returns a rotation representing "no rotation" for the given mode.
*/
Rotation identity_rotation(eRotationModes mode);
/**
* Returns a new rotation, interpolated between `a` and `b` based on `factor`. If `factor` is 0
* the result is `a`.
* If the rotation mode on `a` and `b` does not match, then `b` is converted into the mode of `a`
* first. The returned rotation is always in the rotation mode of `a`.
* Quaternion rotations use spherical interpolation, all other modes use linear.
*/
Rotation rotation_interpolated(const Rotation &a, const Rotation &b, float factor);
/**
* Interpolate the values linearly based on `factor` and returns a new Array. Asserts that both
* spans are the same length. With the factor at `0` the values will match `a`.
*/
Array<float> property_interpolated(Span<float> a, Span<float> b, float factor);
} // namespace ed
} // namespace blender

View File

@@ -0,0 +1,349 @@
/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
#include "BLI_compiler_attrs.h"
#include "BLI_span.hh"
#include "DNA_armature_types.h"
#include "DNA_listBase.h"
#include "DNA_windowmanager_enums.h"
namespace blender {
struct Base;
struct Bone;
struct Depsgraph;
struct EditBone;
struct GPUSelectResult;
struct Main;
struct Mesh;
struct MeshDeformModifierData;
struct Object;
struct ReportList;
struct Scene;
struct SelectPick_Params;
struct UndoType;
struct View3D;
struct ViewLayer;
struct bArmature;
struct bContext;
struct bPoseChannel;
struct wmKeyConfig;
struct wmOperator;
enum eAnimvizCalcRange : uint8_t;
#define BONESEL_ROOT (1u << 29)
#define BONESEL_TIP (1u << 30)
#define BONESEL_BONE (1u << 31)
#define BONESEL_ANY (BONESEL_TIP | BONESEL_ROOT | BONESEL_BONE)
#define EBONE_SELECTABLE(arm, ebone) \
(animrig::bone_is_visible(arm, ebone) && !((ebone)->flag & BONE_UNSELECTABLE))
#define EBONE_EDITABLE(ebone) \
(CHECK_TYPE_INLINE(ebone, EditBone *), \
(((ebone)->flag & BONE_SELECTED) && !((ebone)->flag & BONE_EDITMODE_LOCKED)))
/* Used in `armature_select.cc` and `pose_select.cc`. */
#define BONE_SELECT_PARENT 0
#define BONE_SELECT_CHILD 1
/* `armature_add.cc` */
/**
* Default bone add, returns it selected, but without tail set.
*
* \note should be used everywhere, now it allocates bones still locally in functions.
*/
EditBone *ED_armature_ebone_add(bArmature *arm, const char *name);
EditBone *ED_armature_ebone_add_primitive(Object *obedit_arm, float length, bool view_aligned);
void ED_armature_ebone_copy(EditBone *dest, const EditBone *source);
/**
* Get current armature from the context, including properties editor pinning.
*/
bArmature *ED_armature_context(const bContext *C);
/**
* Adjust bone roll to align Z axis with vector `align_axis` is in local space and is normalized.
*/
float ED_armature_ebone_roll_to_vector(const EditBone *bone,
const float align_axis[3],
bool axis_only);
/**
* \param centermode: 0 == do center, 1 == center new, 2 == center cursor.
*
* \note Exported for use in `editors/object/`.
*/
void ED_armature_origin_set(
Main *bmain, Object *ob, const float cursor[3], int centermode, int around);
/**
* See #BKE_armature_transform for object-mode transform.
*/
void ED_armature_edit_transform(bArmature *arm, const float mat[4][4], bool do_props);
void ED_armature_transform(bArmature *arm, const float mat[4][4], bool do_props);
/* `armature_naming.cc` */
/**
* Ensure the bone name is unique.
* If bone is already in list, pass it as argument to ignore it.
*/
void ED_armature_ebone_unique_name(ListBaseT<EditBone> *ebones, char *name, EditBone *bone);
/**
* Bone Rename (called by UI for renaming a bone).
* Seems messy, but that's what you get with not using pointers but channel names :).
* \warning make sure the original bone was not renamed yet!
*/
void ED_armature_bone_rename(Main *bmain,
bArmature *arm,
const char *oldnamep,
const char *newnamep);
/**
* Renames (by flipping) all selected bones at once.
*
* This way if we are flipping related bones (e.g., Bone.L, Bone.R) at the same time
* all the bones are safely renamed, without conflicting with each other.
*
* \param arm: Armature the bones belong to
* \param bones_names: List of bone conflict elements (#LinkData pointing to names).
* \param do_strip_numbers: if set, try to get rid of dot-numbers at end of bone names.
*/
void ED_armature_bones_flip_names(Main *bmain,
bArmature *arm,
ListBaseT<LinkData> *bones_names,
bool do_strip_numbers);
/* `armature_ops.cc` */
void ED_operatortypes_armature();
void ED_operatormacros_armature();
void ED_keymap_armature(wmKeyConfig *keyconf);
/* `armature_relations.cc` */
/**
* Join armature exec is exported for use in object->join objects operator.
*/
wmOperatorStatus ED_armature_join_objects_exec(bContext *C, wmOperator *op);
/* `armature_select.cc` */
Base *ED_armature_base_and_ebone_from_select_buffer(Span<Base *> bases,
unsigned int select_id,
EditBone **r_ebone);
Object *ED_armature_object_and_ebone_from_select_buffer(Span<Object *> objects,
unsigned int select_id,
EditBone **r_ebone);
Base *ED_armature_base_and_pchan_from_select_buffer(Span<Base *> bases,
unsigned int select_id,
bPoseChannel **r_pchan);
/**
* For callers that don't need the pose channel.
*/
Base *ED_armature_base_and_bone_from_select_buffer(Span<Base *> bases,
unsigned int select_id,
Bone **r_bone);
bool ED_armature_edit_deselect_all(Object *obedit);
bool ED_armature_edit_deselect_all_visible(Object *obedit);
bool ED_armature_edit_deselect_all_multi_ex(Span<Base *> bases);
bool ED_armature_edit_deselect_all_visible_multi_ex(Span<Base *> bases);
bool ED_armature_edit_deselect_all_visible_multi(bContext *C);
/**
* \return True when pick finds an element or the selection changed.
*/
bool ED_armature_edit_select_pick_bone(bContext *C,
Base *basact,
EditBone *ebone,
eBone_Flag selmask,
const SelectPick_Params &params);
/**
* Bone selection picking for armature edit-mode in the view3d.
*/
bool ED_armature_edit_select_pick(bContext *C, const int mval[2], const SelectPick_Params &params);
/**
* Perform a selection operation on elements which have been 'touched',
* use for lasso & border select but can be used elsewhere too.
*
* Tagging is done via #EditBone.temp.i using: #BONESEL_ROOT, #BONESEL_TIP, #BONESEL_BONE
* And optionally ignoring end-points using the #BONESEL_ROOT, #BONESEL_TIP right shifted 16 bits.
* (used when the values are clipped outside the view).
*
* \param sel_op: #eSelectOp type.
*
* \note Visibility checks must be done by the caller.
*/
bool ED_armature_edit_select_op_from_tagged(bArmature *arm, int sel_op);
/* `armature_skinning.cc` */
#define ARM_GROUPS_NAME 1
#define ARM_GROUPS_ENVELOPE 2
#define ARM_GROUPS_AUTO 3
void ED_object_vgroup_calc_from_armature(ReportList *reports,
Depsgraph *depsgraph,
Scene *scene,
Object *ob,
Object *par,
int mode,
bool mirror);
/* `editarmature_undo.cc` */
/** Export for ED_undo_sys. */
void ED_armature_undosys_type(UndoType *ut);
/* `armature_utils.cc` */
/** Sync selection to parent for connected children. */
void ED_armature_edit_sync_selection(ListBaseT<EditBone> *edbo);
/**
* \param clear_connected: When false caller is responsible for keeping the flag in a valid state.
*/
void ED_armature_ebone_remove_ex(bArmature *arm, EditBone *exBone, bool clear_connected);
void ED_armature_ebone_remove(bArmature *arm, EditBone *exBone);
bool ED_armature_ebone_is_child_recursive(EditBone *ebone_parent, EditBone *ebone_child);
/**
* Finds the first parent shared by \a ebone_child
*
* \param ebone_child: Children bones to search
* \param ebone_child_tot: Size of the ebone_child array
* \return The shared parent or NULL.
*/
EditBone *ED_armature_ebone_find_shared_parent(EditBone *ebone_child[],
unsigned int ebone_child_tot);
void ED_armature_ebone_to_mat3(EditBone *ebone, float r_mat[3][3]);
void ED_armature_ebone_to_mat4(EditBone *ebone, float r_mat[4][4]);
void ED_armature_ebone_from_mat3(EditBone *ebone, const float mat[3][3]);
void ED_armature_ebone_from_mat4(EditBone *ebone, const float mat[4][4]);
/**
* Return a pointer to the bone of the given name
*/
EditBone *ED_armature_ebone_find_name(const ListBaseT<EditBone> *edbo, const char *name);
/**
* \see #BKE_pose_channel_get_mirrored (pose-mode, matching function)
*/
EditBone *ED_armature_ebone_get_mirrored(const ListBaseT<EditBone> *edbo, EditBone *ebo);
void ED_armature_ebone_transform_mirror_update(bArmature *arm, EditBone *ebo, bool check_select);
/**
* If edit-bone (partial) selected, copy data.
* context; edit-mode armature, with mirror editing enabled.
*/
void ED_armature_edit_transform_mirror_update(Object *obedit);
/** Put edit-mode back in Object. */
void ED_armature_from_edit(Main *bmain, bArmature *arm);
/** Put armature in edit-mode. */
void ED_armature_to_edit(bArmature *arm);
void ED_armature_edit_free(bArmature *arm);
void ED_armature_ebone_listbase_temp_clear(ListBaseT<EditBone> *lb);
/**
* Free list of bones and their properties.
*/
void ED_armature_ebone_listbase_free(ListBaseT<EditBone> *lb, bool do_id_user);
void ED_armature_ebone_listbase_copy(ListBaseT<EditBone> *lb_dst,
ListBaseT<EditBone> *lb_src,
bool do_id_user);
int ED_armature_ebone_selectflag_get(const EditBone *ebone);
void ED_armature_ebone_selectflag_set(EditBone *ebone, eBone_Flag flag);
void ED_armature_ebone_select_set(EditBone *ebone, bool select);
void ED_armature_ebone_selectflag_enable(EditBone *ebone, eBone_Flag flag);
void ED_armature_ebone_selectflag_disable(EditBone *ebone, eBone_Flag flag);
/* `pose_edit.cc` */
Object *ED_pose_object_from_context(bContext *C);
bool ED_object_posemode_exit_ex(Main *bmain, Object *ob);
bool ED_object_posemode_exit(bContext *C, Object *ob);
/** This function is used to process the necessary updates for. */
bool ED_object_posemode_enter_ex(Main *bmain, Object *ob);
bool ED_object_posemode_enter(bContext *C, Object *ob);
/**
* For the object with pose/action: update paths for those that have got them
* This should selectively update paths that exist...
*
* To be called from various tools that do incremental updates.
*/
void ED_pose_recalculate_paths(bContext *C, Scene *scene, Object *ob, eAnimvizCalcRange range);
/* `pose_select.cc` */
/**
* \return True when pick finds an element or the selection changed.
*/
bool ED_armature_pose_select_pick_bone(const Main &bmain,
const Scene *scene,
ViewLayer *view_layer,
View3D *v3d,
Object *ob,
bPoseChannel *pchan,
const SelectPick_Params &params) ATTR_NONNULL(2, 3, 4, 5);
/**
* Called for mode-less pose selection.
* assumes the active object is still on old situation.
*
* \return True when pick finds an element or the selection changed.
*/
bool ED_armature_pose_select_pick_with_buffer(const Main &bmain,
const Scene *scene,
ViewLayer *view_layer,
View3D *v3d,
Base *base,
const GPUSelectResult *hit_results,
int hits,
const SelectPick_Params &params,
bool do_nearest) ATTR_NONNULL(2, 3, 4, 5, 6);
/**
* While in weight-paint mode, a single pose may be active as well.
* While not common, it's possible we have multiple armatures deforming a mesh.
*
* This function de-selects all other objects, and selects the new base.
* It can't be set to the active object because we need
* to keep this set to the weight paint object.
*/
void ED_armature_pose_select_in_wpaint_mode(const Main &bmain,
const Scene *scene,
ViewLayer *view_layer,
Base *base_select);
bool ED_pose_deselect_all_multi_ex(Span<Base *> bases, int select_mode, bool ignore_visibility);
bool ED_pose_deselect_all_multi(bContext *C, int select_mode, bool ignore_visibility);
/**
* 'select_mode' is usual SEL_SELECT/SEL_DESELECT/SEL_TOGGLE/SEL_INVERT.
* When true, 'ignore_visibility' makes this func also affect invisible bones
* (hidden or on hidden layers).
*/
bool ED_pose_deselect_all(Object *ob, int select_mode, bool ignore_visibility);
void ED_pose_bone_select_tag_update(Object *ob);
/**
* Utility method for changing the selection status of a bone.
* change_active determines whether to change the active bone of the armature when selecting pose
* channels. It is false during range selection otherwise true.
*/
void ED_pose_bone_select(Object *ob, bPoseChannel *pchan, bool select, bool change_active);
/* `meshlaplacian.cc` */
void ED_mesh_deform_bind_callback(Object *object,
MeshDeformModifierData *mmd,
Mesh *cagemesh,
float *vertexcos,
int verts_num,
float cagemat[4][4]);
EditBone *ED_armature_pick_ebone(bContext *C, const int xy[2], bool findunsel, Base **r_base);
bPoseChannel *ED_armature_pick_pchan(bContext *C, const int xy[2], bool findunsel, Base **r_base);
Bone *ED_armature_pick_bone(bContext *C, const int xy[2], bool findunsel, Base **r_base);
} // namespace blender

View File

@@ -0,0 +1,76 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*
* The public API for assets is defined in dedicated headers. This is a utility file that just
* includes all of these.
*/
#pragma once
/* Barely anything here. Just general editor level functions. Actual asset level code is in
* dedicated headers. */
#include "../asset/ED_asset_catalog.hh" // IWYU pragma: export
#include "../asset/ED_asset_library.hh" // IWYU pragma: export
#include "../asset/ED_asset_list.hh" // IWYU pragma: export
#include "../asset/ED_asset_mark_clear.hh" // IWYU pragma: export
#include "../asset/ED_asset_temp_id_consumer.hh" // IWYU pragma: export
#include "../asset/ED_asset_type.hh" // IWYU pragma: export
#include "../asset/ED_asset_filter.hh" // IWYU pragma: export
#include "../asset/ED_asset_import.hh" // IWYU pragma: export
namespace blender {
/** From UI_resources.hh. */
using BIFIconID = int;
struct PointerRNA;
namespace ui {
struct TooltipData;
}
namespace ed::asset {
void asset_tooltip(const asset_system::AssetRepresentation &asset,
ui::TooltipData &tip,
bool include_name = true);
BIFIconID asset_preview_icon_id(const asset_system::AssetRepresentation &asset);
BIFIconID asset_preview_or_icon(const asset_system::AssetRepresentation &asset);
void operatortypes_asset();
/**
* The PointerRNA is expected to have an enum called "asset_library_reference".
*/
const bUserAssetLibrary *get_asset_library_from_opptr(PointerRNA &ptr);
/**
* The PointerRNA is expected to have an enum called "asset_library_reference".
*/
AssetLibraryReference get_asset_library_ref_from_opptr(PointerRNA &ptr);
/**
* Returns the library reference of \a library if set and if it is a library that can be saved to.
* Otherwise falls back to the first enabled user library.
*/
std::optional<AssetLibraryReference> get_user_library_ref_for_save(
const asset_system::AssetLibrary *preferred_library = nullptr);
/**
* For each catalog of the given bUserAssetLibrary call `visit_fn`.
* \param edit_text: If that text is not empty, and not matching an existing catalog path
* `visit_fn` will be called with that text and the icon ICON_ADD.
*/
void visit_library_catalogs_catalog_for_search(
const Main &bmain,
const AssetLibraryReference lib,
StringRef edit_text,
const FunctionRef<void(StringPropertySearchVisitParams)> visit_fn);
} // namespace ed::asset
} // namespace blender

View File

@@ -0,0 +1,64 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edasset
*
* Code for dealing with dynamic asset menus and passing assets to operators with RNA properties.
*/
#pragma once
#include "BLI_string_ref.hh"
#include "RNA_types.hh"
namespace blender {
struct AssetWeakReference;
namespace asset_system {
class AssetCatalogTreeItem;
class AssetLibrary;
class AssetRepresentation;
} // namespace asset_system
namespace ui {
struct Layout;
} // namespace ui
namespace ed::asset {
void draw_menu_for_catalog(const asset_system::AssetCatalogTreeItem &item,
StringRefNull menu_name,
ui::Layout &layout);
void draw_node_menu_for_catalog(const asset_system::AssetCatalogTreeItem &item,
StringRefNull operator_id,
StringRefNull menu_name,
ui::Layout &layout);
void draw_asset_menu_item(const asset_system::AssetRepresentation *asset,
StringRefNull opname,
ui::Layout &layout);
void operator_asset_reference_props_set(const asset_system::AssetRepresentation &asset,
PointerRNA &ptr);
bool operator_asset_reference_props_is_set(PointerRNA &ptr);
void operator_asset_reference_props_register(StructRNA &srna);
const asset_system::AssetRepresentation *find_asset_from_weak_ref(
const bContext &C, const AssetWeakReference &weak_ref, ReportList *reports);
/**
* Load all asset libraries to find an asset from the #operator_asset_reference_props_register
* properties. The loading happens in the background, so there may be no result immediately. In
* that case an "Asset loading is unfinished" report is added.
*
* \note Does not check asset type or meta data.
*/
const asset_system::AssetRepresentation *operator_asset_reference_props_get_asset_from_all_library(
const bContext &C, PointerRNA &ptr, ReportList *reports);
} // namespace ed::asset
} // namespace blender

View File

@@ -0,0 +1,49 @@
/* SPDX-FileCopyrightText: 2013 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
#include "BLI_vector.hh"
#include "DNA_space_types.h"
namespace blender {
struct ScrArea;
struct SpaceProperties;
struct bContext;
struct PointerRNA;
namespace ui {
struct Layout;
} // namespace ui
/**
* Fills an array with the tab context values for the properties editor. -1 signals a separator.
*
* \return The total number of items in the array returned.
*/
Vector<eSpaceButtons_Context> ED_buttons_tabs_list(const SpaceProperties *sbuts,
bool apply_filter = true);
void ED_buttons_visible_tabs_menu(bContext *C, ui::Layout *layout, void * /*arg*/);
void ED_buttons_navbar_menu(bContext *C, ui::Layout *layout, void * /*arg*/);
bool ED_buttons_tab_has_search_result(SpaceProperties *sbuts, int index);
void ED_buttons_search_string_set(SpaceProperties *sbuts, const char *value);
int ED_buttons_search_string_length(SpaceProperties *sbuts);
const char *ED_buttons_search_string_get(SpaceProperties *sbuts);
bool ED_buttons_should_sync_with_outliner(const bContext *C,
const SpaceProperties *sbuts,
ScrArea *area);
void ED_buttons_set_context(const bContext *C,
SpaceProperties *sbuts,
PointerRNA *ptr,
eSpaceButtons_Context context);
} // namespace blender

View File

@@ -0,0 +1,181 @@
/* SPDX-FileCopyrightText: 2009 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
struct ARegion;
struct ImBuf;
struct Main;
struct Mask;
struct MovieClip;
struct SpaceClip;
struct bContext;
struct bScreen;
namespace blender {
/* `clip_editor.cc` */
/**
* Returns true when the following conditions are met:
* - Current space is Space Clip.
* - There is a movie clip opened in it.
*/
bool ED_space_clip_poll(bContext *C);
/**
* Returns true when the following conditions are met:
* - Current space is Space Clip.
* - It is set to Clip view.
*
* It is not required to have movie clip opened for editing.
*/
bool ED_space_clip_view_clip_poll(bContext *C);
bool ED_space_clip_view_clip_with_region_poll(bContext *C);
/**
* Returns true when the following conditions are met:
* - Current space is Space Clip.
* - It is set to Tracking mode.
*
* It is not required to have movie clip opened for editing.
*/
bool ED_space_clip_tracking_poll(bContext *C);
/**
* Returns true when the following conditions are met:
* - Current space is Space Clip.
* - It is set to Mask mode.
*
* It is not required to have mask opened for editing.
*/
bool ED_space_clip_maskedit_poll(bContext *C);
/**
* Returns true when the following conditions are met:
* - Current space is Space Clip.
* - It is set to Mask mode.
* - Mask has visible and editable splines.
*
* It is not required to have mask opened for editing.
*/
bool ED_space_clip_maskedit_visible_splines_poll(bContext *C);
/**
* Returns true when the following conditions are met:
* - Current space is Space Clip.
* - It is set to Mask mode.
* - The space has mask opened.
*/
bool ED_space_clip_maskedit_mask_poll(bContext *C);
/**
* Returns true when the following conditions are met:
* - Current space is Space Clip.
* - It is set to Mask mode.
* - The space has mask opened.
* - Mask has visible and editable splines.
*/
bool ED_space_clip_maskedit_mask_visible_splines_poll(bContext *C);
void ED_space_clip_get_size(const SpaceClip *sc, int *r_width, int *r_height);
void ED_space_clip_get_size_fl(const SpaceClip *sc, float r_size[2]);
void ED_space_clip_get_zoom(const SpaceClip *sc,
const ARegion *region,
float *r_zoomx,
float *r_zoomy);
void ED_space_clip_get_aspect(const SpaceClip *sc, float *r_aspx, float *r_aspy);
void ED_space_clip_get_aspect_dimension_aware(const SpaceClip *sc, float *r_aspx, float *r_aspy);
/**
* Return current frame number in clip space.
*/
int ED_space_clip_get_clip_frame_number(const SpaceClip *sc);
ImBuf *ED_space_clip_get_buffer(const SpaceClip *sc);
ImBuf *ED_space_clip_get_stable_buffer(const SpaceClip *sc,
float loc[2],
float *scale,
float *angle);
bool ED_space_clip_get_position(const SpaceClip *sc,
const ARegion *region,
const int mval[2],
float r_fpos[2]);
/**
* Returns color in linear space, matching #ED_space_image_color_sample().
*/
bool ED_space_clip_color_sample(const SpaceClip *sc,
const ARegion *region,
const int mval[2],
float r_col[3]);
void ED_clip_update_frame(const Main *mainp, int cfra);
bool ED_clip_view_selection(const bContext *C, const ARegion *region, bool fit);
void ED_clip_select_all(const SpaceClip *sc, int action, bool *r_has_selection);
bool ED_clip_can_select(bContext *C);
void ED_clip_point_undistorted_pos(const SpaceClip *sc, const float co[2], float r_co[2]);
void ED_clip_point_stable_pos(
const SpaceClip *sc, const ARegion *region, float x, float y, float *xr, float *yr);
/**
* \brief the reverse of #ED_clip_point_stable_pos(), gets the marker region coords.
* better name here? view_to_track / track_to_view or so?
*/
void ED_clip_point_stable_pos__reverse(const SpaceClip *sc,
const ARegion *region,
const float co[2],
float r_co[2]);
/**
* Takes `event->mval`.
*/
void ED_clip_mouse_pos(const SpaceClip *sc,
const ARegion *region,
const int mval[2],
float r_co[2]);
bool ED_space_clip_check_show_trackedit(const SpaceClip *sc);
bool ED_space_clip_check_show_maskedit(const SpaceClip *sc);
MovieClip *ED_space_clip_get_clip(const SpaceClip *sc);
void ED_space_clip_set_clip(bContext *C, bScreen *screen, SpaceClip *sc, MovieClip *clip);
Mask *ED_space_clip_get_mask(const SpaceClip *sc);
void ED_space_clip_set_mask(bContext *C, SpaceClip *sc, Mask *mask);
/**
* Locked state is used to preserve current clip editor viewport upon changes. Example usage:
*
* \code{.cc}
* ...
*
* ClipViewLockState lock_state;
* ED_clip_view_lock_state_store(C, &lock_state);
*
* <change selection>
*
* ED_clip_view_lock_state_restore_no_jump(C, &lock_state);
* \endcode
*
* These function are to be used from space clip editor context only.
* Otherwise debug builds will assert, release builds will crash.
*/
struct ClipViewLockState {
float offset_x, offset_y;
float lock_offset_x, lock_offset_y;
float zoom;
};
void ED_clip_view_lock_state_store(const bContext *C, ClipViewLockState *state);
void ED_clip_view_lock_state_restore_no_jump(const bContext *C, const ClipViewLockState *state);
/* `clip_ops.cc` */
void ED_operatormacros_clip();
} // namespace blender

View File

@@ -0,0 +1,131 @@
/* SPDX-FileCopyrightText: 2009 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
#include "BLI_span.hh"
#include "DNA_listBase.h"
#include "DNA_windowmanager_enums.h"
namespace blender {
struct BPoint;
struct Base;
struct BezTriple;
struct Curve;
struct EditNurb;
struct KeyBlock;
struct Main;
struct Nurb;
struct Object;
struct SelectPick_Params;
struct Text;
struct UndoType;
struct View3D;
struct bContext;
struct wmKeyConfig;
struct wmOperator;
/* `curve_ops.cc` */
void ED_operatortypes_curve();
void ED_operatormacros_curve();
void ED_keymap_curve(wmKeyConfig *keyconf);
/* `editcurve.cc` */
ListBaseT<Nurb> *object_editcurve_get(Object *ob);
KeyBlock *ED_curve_get_edit_shape_key(const Curve *cu);
/**
* Load editNurb in object.
*/
void ED_curve_editnurb_load(Main *bmain, Object *obedit);
/**
* Make copy in `cu->editnurb`.
*/
void ED_curve_editnurb_make(Object *obedit);
void ED_curve_editnurb_free(Object *obedit);
/**
* \param dist_px: Maximum distance to pick (in pixels).
*/
bool ED_curve_editnurb_select_pick(bContext *C,
const int mval[2],
int dist_px,
const SelectPick_Params &params);
Nurb *ED_curve_add_nurbs_primitive(
bContext *C, Object *obedit, float mat[4][4], int type, int newob);
bool ED_curve_nurb_select_check(const View3D *v3d, const Nurb *nu);
int ED_curve_nurb_select_count(const View3D *v3d, const Nurb *nu);
bool ED_curve_nurb_select_all(const Nurb *nu);
bool ED_curve_nurb_deselect_all(const Nurb *nu);
/**
* This is used externally, by #OBJECT_OT_join.
* TODO: shape keys - as with meshes.
*/
wmOperatorStatus ED_curve_join_objects_exec(bContext *C, wmOperator *op);
/* `editcurve_select.cc` */
bool ED_curve_select_check(const View3D *v3d, const EditNurb *editnurb);
bool ED_curve_deselect_all(EditNurb *editnurb);
bool ED_curve_deselect_all_multi_ex(Span<Base *> bases);
bool ED_curve_deselect_all_multi(bContext *C);
bool ED_curve_select_all(EditNurb *editnurb);
bool ED_curve_select_swap(EditNurb *editnurb, bool hide_handles);
int ED_curve_select_count(const View3D *v3d, const EditNurb *editnurb);
/* `editcurve_undo.cc` */
/** Export for ED_undo_sys */
void ED_curve_undosys_type(UndoType *ut);
/* `editfont.cc` */
void ED_curve_editfont_load(Object *obedit);
void ED_curve_editfont_make(Object *obedit);
void ED_curve_editfont_free(Object *obedit);
void ED_text_to_object(bContext *C, const Text *text, bool split_lines);
void ED_curve_beztcpy(EditNurb *editnurb, BezTriple *dst, BezTriple *src, int count);
void ED_curve_bpcpy(EditNurb *editnurb, BPoint *dst, BPoint *src, int count);
/**
* Return 0 if animation data wasn't changed, 1 otherwise.
*/
int ED_curve_updateAnimPaths(Main *bmain, Curve *cu);
bool ED_curve_active_center(Curve *cu, float center[3]);
/**
* Text box selection.
*
* \return True when pick finds an element or the selection changed.
*/
bool ED_curve_editfont_select_pick(bContext *C,
const int mval[2],
const SelectPick_Params &params);
/* `editfont_undo.cc` */
/** Export for ED_undo_sys. */
void ED_font_undosys_type(UndoType *ut);
#if 0
/* debug only */
void printknots(Object *obedit);
#endif
} // namespace blender

View File

@@ -0,0 +1,594 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
#include "BKE_crazyspace.hh"
#include "BKE_curves.hh"
#include "BLI_index_mask_fwd.hh"
#include "BLI_vector.hh"
#include "BLI_vector_set.hh"
#include "DNA_view3d_types.h"
#include "DNA_windowmanager_enums.h"
#include "ED_select_utils.hh"
#include "ED_view3d.hh"
namespace blender {
struct bContext;
struct Curves;
struct UndoType;
struct rcti;
struct TransVertStore;
struct wmKeyConfig;
struct wmOperator;
struct wmKeyMap;
struct EnumPropertyItem;
namespace bke {
enum class AttrDomain : int8_t;
struct GSpanAttributeWriter;
} // namespace bke
namespace ed::curves {
void operatortypes_curves();
void operatormacros_curves();
void undosys_type_register(UndoType *ut);
void keymap_curves(wmKeyConfig *keyconf);
void ED_operatortypes_curves_pen();
void ED_curves_pentool_modal_keymap(wmKeyConfig *keyconf);
namespace pen_tool {
enum class ElementMode : int8_t {
None = 0,
Point = 1,
Edge = 2,
HandleLeft = 3,
HandleRight = 4,
};
struct ClosestElement {
float distance_squared = std::numeric_limits<float>::max();
ElementMode element_mode;
int point_index = -1;
int curve_index = -1;
float edge_t = -1.0f;
int drawing_index = -1;
bool is_closer(const float new_distance_squared,
const ElementMode new_element_mode,
const float threshold_distance) const;
};
class PenToolOperation {
public:
ViewContext vc;
float threshold_distance;
float threshold_distance_edge;
bool extrude_point;
bool delete_point;
bool insert_point;
bool move_seg;
bool select_point;
bool move_point;
bool cycle_handle_type;
int extrude_handle;
float radius;
bool move_entire;
bool snap_angle;
bool move_handle;
bool point_added;
bool point_removed;
/* Used to go back to `aligned` after `move_handle` becomes `false` */
bool handle_moved;
float4x4 projection;
float2 mouse_co;
float2 xy;
float2 prev_xy;
float2 center_of_mass_co;
ClosestElement closest_element;
std::optional<int> active_drawing_index;
Vector<float4x4> layer_to_world_per_curves;
/* Only used for Grease Pencil. */
Vector<float4x4> layer_to_object_per_curves;
virtual ~PenToolOperation() = default;
virtual float3 project(const float2 &screen_co) const = 0;
virtual IndexMask all_selected_points(int curves_index, IndexMaskMemory &memory) const = 0;
virtual IndexMask visible_bezier_handle_points(int curves_index,
IndexMaskMemory &memory) const = 0;
virtual IndexMask editable_curves(int curves_index, IndexMaskMemory &memory) const = 0;
virtual void tag_curve_changed(int curves_index) const = 0;
virtual bke::CurvesGeometry &get_curves(int curves_index) const = 0;
virtual IndexRange curves_range() const = 0;
virtual void single_point_attributes(bke::CurvesGeometry &curves, int curves_index) const = 0;
/**
* Will return true if a new curve can be created, and report any errors.
*/
virtual bool can_create_new_curve(wmOperator *op) const = 0;
virtual void update_view(bContext *C) const = 0;
virtual std::optional<wmOperatorStatus> initialize(bContext *C,
wmOperator *op,
const wmEvent *event) = 0;
float2 layer_to_screen(const float4x4 &layer_to_object, const float3 &point) const;
float3 screen_to_layer(const float4x4 &layer_to_world,
const float2 &screen_co,
const float3 &depth_point_layer) const;
wmOperatorStatus invoke(bContext *C, wmOperator *op, const wmEvent *event);
wmOperatorStatus modal(bContext *C, wmOperator *op, const wmEvent *event);
};
void pen_tool_common_props(wmOperatorType *ot);
wmKeyMap *ensure_keymap(wmKeyConfig *keyconf);
} // namespace pen_tool
/**
* Return an owning pointer to an array of point normals the same size as the number of control
* points. The normals depend on the normal mode for each curve and the "tilt" attribute and may be
* calculated for the evaluated points and sampled back to the control points.
*/
float (*point_normals_array_create(const Curves *curves_id))[3];
/**
* Get selection attribute names need for given curve and domain.
* Possible outcomes:
* [".selection", ".selection_handle_left", ".selection_handle_right"] if Bezier curves are
* present, [".selection"] otherwise.
*/
Span<StringRef> get_curves_selection_attribute_names(const bke::CurvesGeometry &curves);
/**
* Get writable positions per selection attribute for given curve.
*/
Vector<MutableSpan<float3>> get_curves_positions_for_write(bke::CurvesGeometry &curves);
/**
* Get read-only positions per selection attribute for given curve.
*/
Vector<Span<float3>> get_curves_positions(const bke::CurvesGeometry &curves);
/* Get all possible curve selection attribute names. */
Span<StringRef> get_curves_all_selection_attribute_names();
/**
* Returns [".selection_handle_left", ".selection_handle_right"] if argument contains Bezier
* curves, empty span otherwise.
*/
Span<StringRef> get_curves_bezier_selection_attribute_names(const bke::CurvesGeometry &curves);
/**
* Used to select everything or to delete selection attribute so that it will not have to be
* resized.
*/
void remove_selection_attributes(
bke::MutableAttributeAccessor &attributes,
Span<StringRef> selection_attribute_names = get_curves_all_selection_attribute_names());
/**
* Get the position span associated with the given selection attribute name.
*/
std::optional<Span<float3>> get_selection_attribute_positions(
const bke::CurvesGeometry &curves,
const bke::crazyspace::GeometryDeformation &deformation,
StringRef attribute_name);
using SelectionRangeFn = FunctionRef<void(
IndexRange range, Span<float3> positions, StringRef selection_attribute_name)>;
/**
* Traverses all ranges of control points possible select. Callback function is provided with a
* range being visited, positions (deformed if possible) referenced by the range and selection
* attribute name positions belongs to:
* curves.positions() belong to ".selection",
* curves.handle_positions_left() belong to ".selection_handle_left",
* curves.handle_positions_right() belong to ".selection_handle_right".
*/
void foreach_selectable_point_range(const bke::CurvesGeometry &curves,
const bke::crazyspace::GeometryDeformation &deformation,
eHandleDisplay handle_display,
SelectionRangeFn range_consumer);
/**
* Same logic as in foreach_selectable_point_range, just ranges reference curves instead of
* positions directly. Further positions can be referenced by using `curves.points_by_curve()`
* in a callback function.
*/
void foreach_selectable_curve_range(const bke::CurvesGeometry &curves,
const bke::crazyspace::GeometryDeformation &deformation,
eHandleDisplay handle_display,
SelectionRangeFn range_consumer);
bool object_has_editable_curves(const Main &bmain, const Object &object);
bke::CurvesGeometry primitive_random_sphere(int curves_size, int points_per_curve);
VectorSet<Curves *> get_unique_editable_curves(const bContext &C);
void ensure_surface_deformation_node_exists(bContext &C, Object &curves_ob);
/**
* Allocate an array of #TransVert for cursor/selection snapping (See
* #ED_transverts_create_from_obedit in `view3d_snap.cc`).
* \note The #TransVert elements in \a tvs are expected to write to the positions of \a curves.
*/
void transverts_from_curves_positions_create(bke::CurvesGeometry &curves,
TransVertStore *tvs,
const bool skip_handles);
/**
* Update original curve positions with transform changes.
*/
void transverts_update_curves(bke::CurvesGeometry &curves,
const TransVertStore *tvs,
bool skip_handles);
/* -------------------------------------------------------------------- */
/** \name Poll Functions
* \{ */
bool editable_curves_with_surface_poll(bContext *C);
bool editable_curves_in_edit_mode_poll(bContext *C);
bool curves_with_surface_poll(bContext *C);
bool editable_curves_poll(bContext *C);
bool curves_poll(bContext *C);
/** \} */
/* -------------------------------------------------------------------- */
/** \name Operators
* \{ */
void CURVES_OT_attribute_set(wmOperatorType *ot);
void CURVES_OT_draw(wmOperatorType *ot);
void CURVES_OT_extrude(wmOperatorType *ot);
void CURVES_OT_select_linked_pick(wmOperatorType *ot);
void CURVES_OT_separate(wmOperatorType *ot);
/** \} */
/* -------------------------------------------------------------------- */
/** \name Mask Functions
* \{ */
/**
* Return a mask of all the end points in the curves.
* \param curves_mask: (optional) The curves that should be used in the resulting point mask.
* \param amount_start: The amount of points to mask from the front.
* \param amount_end: The amount of points to mask from the back.
* \param inverted: Invert the resulting mask.
*/
IndexMask end_points(const bke::CurvesGeometry &curves,
int amount_start,
int amount_end,
bool inverted,
IndexMaskMemory &memory);
IndexMask end_points(const bke::CurvesGeometry &curves,
const IndexMask &curves_mask,
int amount_start,
int amount_end,
bool inverted,
IndexMaskMemory &memory);
/** \} */
/* -------------------------------------------------------------------- */
/** \name Selection
*
* Selection on curves can be stored on either attribute domain: either per-curve or per-point. It
* can be stored with a float or boolean data-type. The boolean data-type is faster, smaller, and
* corresponds better to edit-mode selections, but the float data type is useful for soft selection
* (like masking) in sculpt mode.
*
* The attribute API is used to do the necessary type and domain conversions when necessary, and
* can handle most interaction with the selection attribute, but these functions implement some
* helpful utilities on top of that.
* \{ */
void fill_selection_false(GMutableSpan selection);
void fill_selection_true(GMutableSpan selection);
void fill_selection(GMutableSpan selection, bool value);
void fill_selection_false(GMutableSpan selection, const IndexMask &mask);
void fill_selection_true(GMutableSpan selection, const IndexMask &mask);
/**
* Return true if any element is selected, on either domain with either type.
*/
bool has_anything_selected(const bke::CurvesGeometry &curves);
bool has_anything_selected(const bke::CurvesGeometry &curves, bke::AttrDomain selection_domain);
bool has_anything_selected(const bke::CurvesGeometry &curves,
bke::AttrDomain selection_domain,
const IndexMask &mask);
/**
* Return true if any element in the span is selected, on either domain with either type.
*/
bool has_anything_selected(GSpan selection);
bool has_anything_selected(const VArray<bool> &varray, IndexRange range_to_check);
bool has_anything_selected(const VArray<bool> &varray, const IndexMask &indices_to_check);
/**
* Find curves that have any point selected (a selection factor greater than zero),
* or curves that have their own selection factor greater than zero.
*/
IndexMask retrieve_selected_curves(const bke::CurvesGeometry &curves, LinearAllocator<> &memory);
IndexMask retrieve_selected_curves(const Curves &curves_id, LinearAllocator<> &memory);
/**
* Find points that are selected (a selection factor greater than zero),
* or points in curves with a selection factor greater than zero.
*/
IndexMask retrieve_selected_points(const bke::CurvesGeometry &curves, LinearAllocator<> &memory);
IndexMask retrieve_selected_points(const Curves &curves_id, LinearAllocator<> &memory);
/**
* Find points that are selected, for a given attribute_name, requires mask of all Bezier points.
* Note: When retrieving ".selection_handle_left" or ".selection_handle_right" all non-Bezier
* points will be deselected even if the raw attribute is selected.
*/
IndexMask retrieve_selected_points(const bke::CurvesGeometry &curves,
StringRef attribute_name,
const IndexMask &bezier_points,
LinearAllocator<> &memory);
/**
* Find points that are selected (a selection factor greater than zero) or have
* any of their Bezier handle selected.
*/
IndexMask retrieve_all_selected_points(const bke::CurvesGeometry &curves,
int handle_display,
LinearAllocator<> &memory);
/**
* If the selection_id attribute doesn't exist, create it with the requested type (bool or float).
*/
bke::GSpanAttributeWriter ensure_selection_attribute(bke::CurvesGeometry &curves,
bke::AttrDomain selection_domain,
bke::AttrType create_type,
StringRef attribute_name = ".selection");
void foreach_selection_attribute_writer(
bke::CurvesGeometry &curves,
bke::AttrDomain selection_domain,
FunctionRef<void(bke::GSpanAttributeWriter &selection)> fn);
/** Apply a change to a single curve or point. Avoid using this when affecting many elements. */
void apply_selection_operation_at_index(GMutableSpan selection, int index, eSelectOp sel_op);
/**
* (De)select all the curves.
*
* \param mask: (optional) The elements that should be affected. This mask should be in the domain
* of the \a selection_domain.
* \param action: One of #SEL_TOGGLE, #SEL_SELECT, #SEL_DESELECT, or #SEL_INVERT.
* See `ED_select_utils.hh`.
*/
void select_all(bke::CurvesGeometry &curves, bke::AttrDomain selection_domain, int action);
void select_all(bke::CurvesGeometry &curves,
const IndexMask &mask,
bke::AttrDomain selection_domain,
int action);
/**
* Select the points of all curves that have at least one point selected.
*
* \param curves_mask: (optional) The curves that should be affected.
*/
void select_linked(bke::CurvesGeometry &curves, const bool unselect = false);
void select_linked(bke::CurvesGeometry &curves,
const IndexMask &curves_mask,
const bool unselect = false);
/**
* Select alternated points in strokes with already selected points
*
* \param curves_mask: (optional) The curves that should be affected.
*/
void select_alternate(bke::CurvesGeometry &curves, const bool deselect_ends);
void select_alternate(bke::CurvesGeometry &curves,
const IndexMask &curves_mask,
const bool deselect_ends);
/**
* (De)select all the adjacent points of the current selected points.
*
* \param curves_mask: (optional) The curves that should be affected.
*/
void select_adjacent(bke::CurvesGeometry &curves, bool deselect);
void select_adjacent(bke::CurvesGeometry &curves, const IndexMask &curves_mask, bool deselect);
/**
* Helper struct for `closest_elem_find_screen_space`.
*/
struct FindClosestData {
int index = -1;
float distance_sq = FLT_MAX;
};
/**
* Find the closest screen-space point or curve in projected region-space.
*
* \return A new point or curve closer than the \a initial input, if one exists.
*/
std::optional<FindClosestData> closest_elem_find_screen_space(const ViewContext &vc,
OffsetIndices<int> points_by_curve,
Span<float3> deformed_positions,
const VArray<bool> &cyclic,
const float4x4 &projection,
const IndexMask &mask,
bke::AttrDomain domain,
int2 coord,
const FindClosestData &initial);
/**
* Select points or curves in a (screen-space) rectangle.
*/
bool select_box(const ViewContext &vc,
bke::CurvesGeometry &curves,
const bke::crazyspace::GeometryDeformation &deformation,
const float4x4 &projection,
const IndexMask &selection_mask,
const IndexMask &bezier_mask,
bke::AttrDomain selection_domain,
const rcti &rect,
eSelectOp sel_op);
/**
* Select points or curves in a (screen-space) poly shape.
*/
bool select_lasso(const ViewContext &vc,
bke::CurvesGeometry &curves,
const bke::crazyspace::GeometryDeformation &deformation,
const float4x4 &projection,
const IndexMask &selection_mask,
const IndexMask &bezier_mask,
bke::AttrDomain selection_domain,
Span<int2> lasso_coords,
eSelectOp sel_op);
/**
* Select points or curves in a (screen-space) circle.
*/
bool select_circle(const ViewContext &vc,
bke::CurvesGeometry &curves,
const bke::crazyspace::GeometryDeformation &deformation,
const float4x4 &projection,
const IndexMask &selection_mask,
const IndexMask &bezier_mask,
bke::AttrDomain selection_domain,
int2 coord,
float radius,
eSelectOp sel_op);
/**
* Mask of points adjacent to a selected point, or unselected point if deselect is true.
*/
IndexMask select_adjacent_mask(const bke::CurvesGeometry &curves,
StringRef attribute_name,
bool deselect,
IndexMaskMemory &memory);
IndexMask select_adjacent_mask(const bke::CurvesGeometry &curves,
const IndexMask &curves_mask,
StringRef attribute_name,
bool deselect,
IndexMaskMemory &memory);
/**
* Select points or curves in a (screen-space) rectangle.
*/
IndexMask select_box_mask(const ViewContext &vc,
const bke::CurvesGeometry &curves,
const bke::crazyspace::GeometryDeformation &deformation,
const float4x4 &projection,
const IndexMask &selection_mask,
const IndexMask &bezier_mask,
bke::AttrDomain selection_domain,
StringRef attribute_name,
const rcti &rect,
IndexMaskMemory &memory);
/**
* Select points or curves in a (screen-space) poly shape.
*/
IndexMask select_lasso_mask(const ViewContext &vc,
const bke::CurvesGeometry &curves,
const bke::crazyspace::GeometryDeformation &deformation,
const float4x4 &projection,
const IndexMask &selection_mask,
const IndexMask &bezier_mask,
bke::AttrDomain selection_domain,
StringRef attribute_name,
Span<int2> lasso_coords,
IndexMaskMemory &memory);
/**
* Select points or curves in a (screen-space) circle.
*/
IndexMask select_circle_mask(const ViewContext &vc,
const bke::CurvesGeometry &curves,
const bke::crazyspace::GeometryDeformation &deformation,
const float4x4 &projection,
const IndexMask &selection_mask,
const IndexMask &bezier_mask,
bke::AttrDomain selection_domain,
StringRef attribute_name,
int2 coord,
float radius,
IndexMaskMemory &memory);
/** \} */
/* -------------------------------------------------------------------- */
/** \name Editing
* \{ */
/**
* Remove (dissolve) selected curves or points based on the ".selection" attribute.
* \returns true if any point or curve was removed.
*/
bool remove_selection(bke::CurvesGeometry &curves, bke::AttrDomain selection_domain);
void duplicate_points(bke::CurvesGeometry &curves, const IndexMask &mask);
void duplicate_curves(bke::CurvesGeometry &curves, const IndexMask &mask);
void separate_points(const bke::CurvesGeometry &curves,
const IndexMask &points_to_separate,
bke::CurvesGeometry &separated,
bke::CurvesGeometry &retained);
bke::CurvesGeometry split_points(const bke::CurvesGeometry &curves,
const IndexMask &points_to_split);
/**
* Adds new curves to \a curves.
* \param new_sizes: The new size for each curve. Sizes must be > 0.
*/
void add_curves(bke::CurvesGeometry &curves, Span<int> new_sizes);
/**
* Resizes the curves in \a curves.
* \param curves_to_resize: The curves that should be resized.
* \param new_sizes: The new size for each curve in \a curves_to_resize. If the size is smaller,
* the curve is trimmed from the end. If the size is larger, the end is extended and all attributes
* are default initialized. Sizes must be > 0.
*/
void resize_curves(bke::CurvesGeometry &curves,
const IndexMask &curves_to_resize,
Span<int> new_sizes);
/**
* Reorders the curves in \a curves.
* \param old_by_new_indices_map: An index mapping where each value is the target index for the
* reorder curves.
*/
void reorder_curves(bke::CurvesGeometry &curves, Span<int> old_by_new_indices_map);
wmOperatorStatus join_objects_exec(bContext *C, wmOperator *op);
enum class SetHandleType : uint8_t {
Free = 0,
Auto = 1,
Vector = 2,
Align = 3,
Toggle = 4,
};
extern const EnumPropertyItem rna_enum_set_handle_type_items[];
/** \} */
} // namespace ed::curves
} // namespace blender

View File

@@ -0,0 +1,15 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
namespace blender {
void ED_operatortypes_sculpt_curves();
} // namespace blender

View File

@@ -0,0 +1,313 @@
/* SPDX-FileCopyrightText: 2008 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
/* Datafiles embedded in Blender */
extern int datatoc_startup_blend_size;
extern const char datatoc_startup_blend[];
extern int datatoc_preview_blend_size;
extern const char datatoc_preview_blend[];
extern int datatoc_preview_grease_pencil_blend_size;
extern const char datatoc_preview_grease_pencil_blend[];
extern int datatoc_splash_png_size;
extern const char datatoc_splash_png[];
extern int datatoc_bfont_pfb_size;
extern const char datatoc_bfont_pfb[];
/* Brush icon datafiles */
/* TODO: this could be simplified by putting all
* the brush icons in one file */
extern int datatoc_add_png_size;
extern const char datatoc_add_png[];
extern int datatoc_blob_png_size;
extern const char datatoc_blob_png[];
extern int datatoc_blur_png_size;
extern const char datatoc_blur_png[];
extern int datatoc_clay_png_size;
extern const char datatoc_clay_png[];
extern int datatoc_claystrips_png_size;
extern const char datatoc_claystrips_png[];
extern int datatoc_clone_png_size;
extern const char datatoc_clone_png[];
extern int datatoc_crease_png_size;
extern const char datatoc_crease_png[];
extern int datatoc_darken_png_size;
extern const char datatoc_darken_png[];
extern int datatoc_draw_png_size;
extern const char datatoc_draw_png[];
extern int datatoc_fill_png_size;
extern const char datatoc_fill_png[];
extern int datatoc_flatten_png_size;
extern const char datatoc_flatten_png[];
extern int datatoc_grab_png_size;
extern const char datatoc_grab_png[];
extern int datatoc_inflate_png_size;
extern const char datatoc_inflate_png[];
extern int datatoc_layer_png_size;
extern const char datatoc_layer_png[];
extern int datatoc_lighten_png_size;
extern const char datatoc_lighten_png[];
extern int datatoc_mask_png_size;
extern const char datatoc_mask_png[];
extern int datatoc_mix_png_size;
extern const char datatoc_mix_png[];
extern int datatoc_multiply_png_size;
extern const char datatoc_multiply_png[];
extern int datatoc_nudge_png_size;
extern const char datatoc_nudge_png[];
extern int datatoc_paint_select_png_size;
extern const char datatoc_paint_select_png[];
extern int datatoc_pinch_png_size;
extern const char datatoc_pinch_png[];
extern int datatoc_scrape_png_size;
extern const char datatoc_scrape_png[];
extern int datatoc_smear_png_size;
extern const char datatoc_smear_png[];
extern int datatoc_smooth_png_size;
extern const char datatoc_smooth_png[];
extern int datatoc_snake_hook_png_size;
extern const char datatoc_snake_hook_png[];
extern int datatoc_soften_png_size;
extern const char datatoc_soften_png[];
extern int datatoc_subtract_png_size;
extern const char datatoc_subtract_png[];
extern int datatoc_texdraw_png_size;
extern const char datatoc_texdraw_png[];
extern int datatoc_texfill_png_size;
extern const char datatoc_texfill_png[];
extern int datatoc_texmask_png_size;
extern const char datatoc_texmask_png[];
extern int datatoc_thumb_png_size;
extern const char datatoc_thumb_png[];
extern int datatoc_twist_png_size;
extern const char datatoc_twist_png[];
extern int datatoc_vertexdraw_png_size;
extern const char datatoc_vertexdraw_png[];
/* Matcap files */
extern int datatoc_mc01_jpg_size;
extern const char datatoc_mc01_jpg[];
extern int datatoc_mc02_jpg_size;
extern const char datatoc_mc02_jpg[];
extern int datatoc_mc03_jpg_size;
extern const char datatoc_mc03_jpg[];
extern int datatoc_mc04_jpg_size;
extern const char datatoc_mc04_jpg[];
extern int datatoc_mc05_jpg_size;
extern const char datatoc_mc05_jpg[];
extern int datatoc_mc06_jpg_size;
extern const char datatoc_mc06_jpg[];
extern int datatoc_mc07_jpg_size;
extern const char datatoc_mc07_jpg[];
extern int datatoc_mc08_jpg_size;
extern const char datatoc_mc08_jpg[];
extern int datatoc_mc09_jpg_size;
extern const char datatoc_mc09_jpg[];
extern int datatoc_mc10_jpg_size;
extern const char datatoc_mc10_jpg[];
extern int datatoc_mc11_jpg_size;
extern const char datatoc_mc11_jpg[];
extern int datatoc_mc12_jpg_size;
extern const char datatoc_mc12_jpg[];
extern int datatoc_mc13_jpg_size;
extern const char datatoc_mc13_jpg[];
extern int datatoc_mc14_jpg_size;
extern const char datatoc_mc14_jpg[];
extern int datatoc_mc15_jpg_size;
extern const char datatoc_mc15_jpg[];
extern int datatoc_mc16_jpg_size;
extern const char datatoc_mc16_jpg[];
extern int datatoc_mc17_jpg_size;
extern const char datatoc_mc17_jpg[];
extern int datatoc_mc18_jpg_size;
extern const char datatoc_mc18_jpg[];
extern int datatoc_mc19_jpg_size;
extern const char datatoc_mc19_jpg[];
extern int datatoc_mc20_jpg_size;
extern const char datatoc_mc20_jpg[];
extern int datatoc_mc21_jpg_size;
extern const char datatoc_mc21_jpg[];
extern int datatoc_mc22_jpg_size;
extern const char datatoc_mc22_jpg[];
extern int datatoc_mc23_jpg_size;
extern const char datatoc_mc23_jpg[];
extern int datatoc_mc24_jpg_size;
extern const char datatoc_mc24_jpg[];
/* grease pencil sculpt brushes files */
extern int datatoc_gp_brush_smooth_png_size;
extern const char datatoc_gp_brush_smooth_png[];
extern int datatoc_gp_brush_thickness_png_size;
extern const char datatoc_gp_brush_thickness_png[];
extern int datatoc_gp_brush_strength_png_size;
extern const char datatoc_gp_brush_strength_png[];
extern int datatoc_gp_brush_grab_png_size;
extern const char datatoc_gp_brush_grab_png[];
extern int datatoc_gp_brush_push_png_size;
extern const char datatoc_gp_brush_push_png[];
extern int datatoc_gp_brush_twist_png_size;
extern const char datatoc_gp_brush_twist_png[];
extern int datatoc_gp_brush_pinch_png_size;
extern const char datatoc_gp_brush_pinch_png[];
extern int datatoc_gp_brush_randomize_png_size;
extern const char datatoc_gp_brush_randomize_png[];
extern int datatoc_gp_brush_clone_png_size;
extern const char datatoc_gp_brush_clone_png[];
extern int datatoc_gp_brush_weight_png_size;
extern const char datatoc_gp_brush_weight_png[];
extern int datatoc_gp_brush_pencil_png_size;
extern const char datatoc_gp_brush_pencil_png[];
extern int datatoc_gp_brush_pen_png_size;
extern const char datatoc_gp_brush_pen_png[];
extern int datatoc_gp_brush_ink_png_size;
extern const char datatoc_gp_brush_ink_png[];
extern int datatoc_gp_brush_inknoise_png_size;
extern const char datatoc_gp_brush_inknoise_png[];
extern int datatoc_gp_brush_block_png_size;
extern const char datatoc_gp_brush_block_png[];
extern int datatoc_gp_brush_marker_png_size;
extern const char datatoc_gp_brush_marker_png[];
extern int datatoc_gp_brush_fill_png_size;
extern const char datatoc_gp_brush_fill_png[];
extern int datatoc_gp_brush_airbrush_png_size;
extern const char datatoc_gp_brush_airbrush_png[];
extern int datatoc_gp_brush_chisel_png_size;
extern const char datatoc_gp_brush_chisel_png[];
extern int datatoc_gp_brush_erase_soft_png_size;
extern const char datatoc_gp_brush_erase_soft_png[];
extern int datatoc_gp_brush_erase_hard_png_size;
extern const char datatoc_gp_brush_erase_hard_png[];
extern int datatoc_gp_brush_erase_stroke_png_size;
extern const char datatoc_gp_brush_erase_stroke_png[];
/* curves sculpt brushes files */
extern int datatoc_curves_sculpt_add_png_size;
extern const char datatoc_curves_sculpt_add_png[];
extern int datatoc_curves_sculpt_comb_png_size;
extern const char datatoc_curves_sculpt_comb_png[];
extern int datatoc_curves_sculpt_cut_png_size;
extern const char datatoc_curves_sculpt_cut_png[];
extern int datatoc_curves_sculpt_delete_png_size;
extern const char datatoc_curves_sculpt_delete_png[];
extern int datatoc_curves_sculpt_density_png_size;
extern const char datatoc_curves_sculpt_density_png[];
extern int datatoc_curves_sculpt_grow_shrink_png_size;
extern const char datatoc_curves_sculpt_grow_shrink_png[];
extern int datatoc_curves_sculpt_pinch_png_size;
extern const char datatoc_curves_sculpt_pinch_png[];
extern int datatoc_curves_sculpt_puff_png_size;
extern const char datatoc_curves_sculpt_puff_png[];
extern int datatoc_curves_sculpt_slide_png_size;
extern const char datatoc_curves_sculpt_slide_png[];
extern int datatoc_curves_sculpt_smooth_png_size;
extern const char datatoc_curves_sculpt_smooth_png[];
extern int datatoc_curves_sculpt_snake_hook_png_size;
extern const char datatoc_curves_sculpt_snake_hook_png[];
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,140 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edfile
*/
#pragma once
#include "BLO_readfile.hh"
namespace blender {
/**
* File indexing for the file/asset browser.
*
* This file contains an API to create indexing functionality when listing blend files in
* the file browser.
*
* To implement a custom indexer a `FileIndexerType` struct should be made and passed to the
* `filelist_setindexer` function.
*/
struct LinkNode;
/**
* Result code of the `read_index` callback.
*/
enum eFileIndexerResult {
/**
* File listing entries are loaded from the index. Reading entries from the blend file itself
* should be skipped.
*/
FILE_INDEXER_ENTRIES_LOADED,
/**
* Index isn't available or not up to date. Entries should be read from the blend file and
* `update_index` must be called to update the index.
*/
FILE_INDEXER_NEEDS_UPDATE,
};
/**
* FileIndexerEntry contains all data that is required to create a file listing entry.
*/
struct FileIndexerEntry {
BLODataBlockInfo datablock_info;
short idcode;
};
/**
* Contains all entries of a blend file.
*/
struct FileIndexerEntries {
LinkNode /*FileIndexerEntry*/ *entries;
};
using FileIndexerInitUserDataFunc = void *(*)(const char *root_directory,
size_t root_directory_maxlen);
using FileIndexerFreeUserDataFunc = void (*)(void *);
using FileIndexerFinishedFunc = void (*)(void *);
using FileIndexerReadIndexFunc = eFileIndexerResult (*)(const char *file_name,
FileIndexerEntries *entries,
int *r_read_entries_len,
void *user_data);
using FileIndexerUpdateIndexFunc = void (*)(const char *file_name,
FileIndexerEntries *entries,
void *user_data);
struct FileIndexerType {
/**
* Is called at the beginning of the file listing process. An indexer can
* setup needed data. The result of this function will be passed around as `user_data` parameter.
*
* This is an optional callback.
*/
FileIndexerInitUserDataFunc init_user_data;
/**
* Is called at the end of the file listing process. An indexer can free the data that it created
* during the file listing process.
*
* This is an optional callback.
*/
FileIndexerFreeUserDataFunc free_user_data;
/**
* Is called at the end of the file listing process (before the `free_user_data`) where indexes
* can perform clean-ups.
*
* This is an optional callback. Called when listing files completed.
*/
FileIndexerFinishedFunc filelist_finished;
/**
* Is called for each blend file being listed to read data from the index.
*
* Read entries should be added to given `entries` parameter (type: `FileIndexerEntries`).
* `*r_read_entries_len` must be set to the number of read entries.
* and the function must return `eFileIndexerResult::FILE_INDEXER_ENTRIES_LOADED`.
* In this case the blend file will not be opened and the FileIndexerEntry added to `entries`
* will be used as the content of the file.
*
* When the index isn't available or could not be used no entries must be added to the
* entries field, `r_read_entries_len` must be set to `0` and the function must return
* `eFileIndexerResult::FILE_INDEXER_NEEDS_UPDATE`. In this case the blend file will read from
* the blend file and the `update_index` function will be called.
*/
FileIndexerReadIndexFunc read_index;
/**
* Update an index of a blend file.
*
* Is called after reading entries from the file when the result of `read_index` was
* `eFileIndexerResult::FILE_INDEXER_NEED_UPDATE`. The callback should update the index so the
* next time that read_index is called it will read the entries from the index.
*/
FileIndexerUpdateIndexFunc update_index;
};
/* `file_indexer.cc` */
/** Removes all entries inside the given `indexer_entries`. */
void ED_file_indexer_entries_clear(FileIndexerEntries *indexer_entries);
/**
* Adds all entries from the given `datablock_infos` to the `indexer_entries`.
* The datablock_infos must only contain data for a single IDType. The specific IDType must be
* passed in the `idcode` parameter.
*
* \note This can "steal" data contained in \a datablock_infos, to avoid expensive copies, which is
* supported by the #BLODataBlockInfo type.
*/
void ED_file_indexer_entries_extend_from_datablock_infos(
FileIndexerEntries *indexer_entries,
LinkNode * /*BLODataBlockInfo*/ datablock_infos,
int idcode);
} // namespace blender

View File

@@ -0,0 +1,279 @@
/* SPDX-FileCopyrightText: 2008 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
#include <string>
#include "BLI_vector.hh"
#include "DNA_uuid_types.h"
namespace blender {
struct ARegion;
struct FileAssetSelectParams;
struct FileDirEntry;
struct FileSelectParams;
struct FSMenu;
struct FSMenuEntry;
struct ID;
struct ScrArea;
struct SpaceFile;
struct bContext;
struct bScreen;
namespace ui {
struct Block;
}
struct wmOperator;
struct wmWindow;
struct wmWindowManager;
struct View2D;
struct rcti;
namespace asset_system {
class AssetLibrary;
}
enum eFileSortType : short;
#define FILE_LAYOUT_HOR 1
#define FILE_LAYOUT_VER 2
enum FileAttributeColumnType {
COLUMN_NONE = -1,
COLUMN_NAME = 0,
COLUMN_DATETIME,
COLUMN_SIZE,
ATTRIBUTE_COLUMN_MAX
};
struct FileAttributeColumn {
/** UI name for this column */
const char *name;
float width;
/** The sort type to use when sorting by this column. */
eFileSortType sort_type;
/** Alignment of column texts, header text is always left aligned */
int text_align; /* eFontStyle_Align */
};
struct FileLayout {
/* view settings - XXX: move into its own struct. */
int offset_top;
/** Height of the header for the different FileAttributeColumn's. */
int attribute_column_header_h;
int prv_w;
int prv_h;
/** Extra padding to add above any files. Used for horizontal and column list views. */
int list_padding_top;
/** Width to draw the file's "tile" (matches the highlight background) with. `tile_border_x` will
* be added before and after it as padding around the tile. */
int tile_w;
/** Height to draw the file's "tile" (matches the highlight background) with. `tile_border_y`
* will be added above and below it as padding around the tile. */
int tile_h;
int tile_border_x;
int tile_border_y;
int prv_border_x;
int prv_border_y;
int rows;
/**
* Those are the major layout columns the files are distributed across,
* not to be confused with `attribute_columns` array below.
*/
int flow_columns;
int width;
int height;
int flag;
int dirty;
int text_line_height;
int text_lines_count;
/**
* The columns for each item (name, modification date/time, size).
* Not to be confused with the `flow_columns` above.
*/
FileAttributeColumn attribute_columns[ATTRIBUTE_COLUMN_MAX];
/** When we change display size, we may have to update static strings like size of files. */
short curr_size;
};
struct FileSelection {
int first;
int last;
};
/**
* If needed, create and return the file select parameters for the active browse mode.
*/
FileSelectParams *ED_fileselect_ensure_active_params(SpaceFile *sfile);
/**
* Get the file select parameters for the active browse mode.
*/
FileSelectParams *ED_fileselect_get_active_params(const SpaceFile *sfile);
FileSelectParams *ED_fileselect_get_file_params(const SpaceFile *sfile);
FileAssetSelectParams *ED_fileselect_get_asset_params(const SpaceFile *sfile);
bool ED_fileselect_is_local_asset_library(const SpaceFile *sfile);
void ED_fileselect_set_params_from_userdef(SpaceFile *sfile);
/**
* Update the user-preference data for the file space. In fact, this also contains some
* non-FileSelectParams data, but we can safely ignore this.
*/
void ED_fileselect_params_to_userdef(SpaceFile *sfile);
void ED_fileselect_init_layout(SpaceFile *sfile, ARegion *region);
FileLayout *ED_fileselect_get_layout(SpaceFile *sfile, ARegion *region);
int ED_fileselect_layout_numfiles(FileLayout *layout, ARegion *region);
int ED_fileselect_layout_offset(FileLayout *layout, int x, int y);
FileSelection ED_fileselect_layout_offset_rect(FileLayout *layout, const rcti *rect);
/**
* Get the currently visible bounds of the layout in screen space. Matches View2D.mask minus the
* top column-header row.
*/
void ED_fileselect_layout_maskrect(const FileLayout *layout, const View2D *v2d, rcti *r_rect);
bool ED_fileselect_layout_is_inside_pt(const FileLayout *layout, const View2D *v2d, int x, int y);
bool ED_fileselect_layout_isect_rect(const FileLayout *layout,
const View2D *v2d,
const rcti *rect,
rcti *r_dst);
void ED_fileselect_layout_tilepos(const FileLayout *layout, int tile, int *x, int *y);
void ED_operatormacros_file();
void ED_fileselect_clear(wmWindowManager *wm, SpaceFile *sfile);
void ED_fileselect_clear_main_assets(wmWindowManager *wm, SpaceFile *sfile);
void ED_fileselect_exit(wmWindowManager *wm, SpaceFile *sfile);
bool ED_fileselect_is_file_browser(const SpaceFile *sfile);
bool ED_fileselect_is_asset_browser(const SpaceFile *sfile);
asset_system::AssetLibrary *ED_fileselect_active_asset_library_get(const SpaceFile *sfile);
ID *ED_fileselect_active_asset_get(const SpaceFile *sfile);
void ED_fileselect_activate_asset_catalog(const SpaceFile *sfile, bUUID catalog_id);
/**
* Resolve this space's #eFileAssetImportMethod to the #eAssetImportMethod (note the different
* type) to be used for the actual import of a specific asset.
* - If the asset system dictates a certain import method, this will be returned.
* - If the Asset Browser is set to follow the Preferences (#FILE_ASSET_IMPORT_FOLLOW_PREFS), the
* asset system determines the import method (which is the default from the Preferences). -1 is
* returned if the asset system doesn't specify a method (e.g. because the asset library doesn't
* come from the Preferences).
* - Otherwise, the Asset Browser determines (possibly overrides) the import method.
*
* \return -1 on error, for example when #FILE_ASSET_IMPORT_FOLLOW_PREFS was requested but the
* active asset library reference couldn't be found in the preferences.
*/
int /* #eAssetImportMethod */ ED_fileselect_asset_import_method_get(const SpaceFile *sfile,
const FileDirEntry *file);
/**
* Activate and select the file that corresponds to the given ID.
* Pass deferred=true to wait for the next refresh before activating.
*/
void ED_fileselect_activate_by_id(SpaceFile *sfile, ID *asset_id, bool deferred);
void ED_fileselect_deselect_all(SpaceFile *sfile);
void ED_fileselect_activate_by_relpath(SpaceFile *sfile, const char *relative_path);
void ED_fileselect_window_params_get(const wmWindow *win, int r_win_size[2], bool *r_is_maximized);
/**
* Return the File Browser area in which \a file_operator is active.
*/
ScrArea *ED_fileselect_handler_area_find(const wmWindow *win, const wmOperator *file_operator);
/**
* Check if there is any area in \a win that acts as a modal File Browser (#SpaceFile.op is set)
* and return it.
*/
ScrArea *ED_fileselect_handler_area_find_any_with_op(const wmWindow *win);
/**
* If filepath property is not set on the operator, sets it to
* the blend file path (or untitled if file is not saved yet) with the given extension.
*/
void ED_fileselect_ensure_default_filepath(bContext *C, wmOperator *op, const char *extension);
Vector<std::string> ED_fileselect_selected_files_full_paths(const SpaceFile *sfile);
/* TODO: Maybe we should move this to BLI?
* On the other hand, it's using defines from space-file area, so not sure... */
int ED_path_extension_type(const char *path);
int ED_file_extension_icon(const char *path);
int ED_file_icon(const FileDirEntry *file);
void ED_file_read_bookmarks();
/**
* Support updating the directory even when this isn't the active space
* needed so RNA properties update function isn't context sensitive, see #70255.
*/
void ED_file_change_dir_ex(bContext *C, ScrArea *area);
void ED_file_change_dir(bContext *C);
void ED_file_path_button(bScreen *screen,
SpaceFile *sfile,
FileSelectParams *params,
ui::Block *block);
/* File menu stuff */
/* FSMenuEntry's without paths indicate separators */
struct FSMenuEntry {
FSMenuEntry *next;
char *path;
char name[/*FILE_MAXFILE*/ 256];
short save;
int icon;
};
enum FSMenuCategory {
FS_CATEGORY_SYSTEM,
FS_CATEGORY_SYSTEM_BOOKMARKS,
FS_CATEGORY_BOOKMARKS,
FS_CATEGORY_RECENT,
/** For internal use, a list of known paths that are used to match paths to icons and names. */
FS_CATEGORY_OTHER,
};
enum FSMenuInsert {
FS_INSERT_SORTED = (1 << 0),
FS_INSERT_SAVE = (1 << 1),
/** moves the item to the front of the list when its not already there */
FS_INSERT_FIRST = (1 << 2),
/** just append to preserve delivered order */
FS_INSERT_LAST = (1 << 3),
};
FSMenu *ED_fsmenu_get();
FSMenuEntry *ED_fsmenu_get_category(FSMenu *fsmenu, FSMenuCategory category);
void ED_fsmenu_set_category(FSMenu *fsmenu, FSMenuCategory category, FSMenuEntry *fsm_head);
int ED_fsmenu_get_nentries(FSMenu *fsmenu, FSMenuCategory category);
FSMenuEntry *ED_fsmenu_get_entry(FSMenu *fsmenu, FSMenuCategory category, int idx);
char *ED_fsmenu_entry_get_path(FSMenuEntry *fsentry);
void ED_fsmenu_entry_set_path(FSMenuEntry *fsentry, const char *path);
char *ED_fsmenu_entry_get_name(FSMenuEntry *fsentry);
void ED_fsmenu_entry_set_name(FSMenuEntry *fsentry, const char *name);
int ED_fsmenu_entry_get_icon(FSMenuEntry *fsentry);
void ED_fsmenu_entry_set_icon(FSMenuEntry *fsentry, int icon);
} // namespace blender

View File

@@ -0,0 +1,94 @@
/* SPDX-FileCopyrightText: 2020 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
#include <string>
#include "BLI_generic_pointer.hh"
#include "BLI_string_ref.hh"
#include "BKE_screen.hh"
namespace blender {
struct ReportList;
struct PointerRNA;
struct PropertyRNA;
class AttributeOwner;
namespace bke {
enum class AttrDomain : int8_t;
enum class AttrType : int16_t;
class MutableAttributeAccessor;
} // namespace bke
namespace nodes::eval_log {
class NodesEvalLog;
}
namespace ed::geometry {
/* -------------------------------------------------------------------- */
/** \name Attribute Value RNA Property Helpers
*
* Functions to make it easier to register RNA properties for the various attribute types and
* retrieve/set their values.
* \{ */
StringRefNull rna_property_name_for_type(bke::AttrType type);
PropertyRNA *rna_property_for_type(PointerRNA &ptr, const bke::AttrType type);
void register_rna_properties_for_attribute_types(StructRNA &srna);
GPointer rna_property_for_attribute_type_retrieve_value(PointerRNA &ptr,
const bke::AttrType type,
void *buffer);
void rna_property_for_attribute_type_set_value(PointerRNA &ptr, PropertyRNA &prop, GPointer value);
bool attribute_set_poll(bContext &C, const ID &object_data);
/** \} */
void operatortypes_geometry();
/**
* Re-register all operator types for node tool assets and local node groups. This process
* unregisters old operators.
*/
void register_node_group_operators(const bContext &C);
void ui_template_node_operator_registration_errors(ui::Layout &layout, StringRefNull idname_py);
/**
* Convert an attribute with the given name to a new type and domain.
* The attribute must already exist.
*
* \note Does not support meshes in edit mode.
*/
bool convert_attribute(AttributeOwner &owner,
bke::MutableAttributeAccessor attributes,
StringRef name,
bke::AttrDomain dst_domain,
bke::AttrType dst_type,
ReportList *reports);
struct GeoOperatorLog {
std::string node_group_name;
std::unique_ptr<nodes::eval_log::NodesEvalLog> log;
GeoOperatorLog() = default;
~GeoOperatorLog();
};
const GeoOperatorLog &node_group_operator_static_eval_log();
MenuType node_group_operator_assets_menu();
MenuType node_group_operator_assets_menu_unassigned();
void ui_template_node_operator_asset_menu_items(ui::Layout &layout,
const bContext &C,
StringRef path);
void ui_template_node_operator_asset_root_items(ui::Layout &layout, const bContext &C);
} // namespace ed::geometry
} // namespace blender

View File

@@ -0,0 +1,266 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup wm
*
* \name Generic Gizmos.
*
* This is exposes predefined gizmos for re-use.
*/
#pragma once
#include "DNA_scene_types.h"
namespace blender {
struct bContext;
struct wmGizmo;
struct wmGizmoGroup;
namespace ed::transform {
struct SnapObjectContext;
}
/* initialize gizmos */
void ED_gizmotypes_arrow_3d();
void ED_gizmotypes_button_2d();
void ED_gizmotypes_cage_2d();
void ED_gizmotypes_cage_3d();
void ED_gizmotypes_dial_3d();
void ED_gizmotypes_move_3d();
void ED_gizmotypes_facemap_3d();
void ED_gizmotypes_preselect_3d();
void ED_gizmotypes_primitive_3d();
void ED_gizmotypes_blank_3d();
void ED_gizmotypes_snap_3d();
/* -------------------------------------------------------------------- */
/* Shape Presets
*
* Intended to be called by custom draw functions.
*/
/* `gizmo_library_presets.cc` */
void ED_gizmo_draw_preset_box(const wmGizmo *gz, const float mat[4][4], int select_id);
void ED_gizmo_draw_preset_arrow(const wmGizmo *gz, const float mat[4][4], int axis, int select_id);
void ED_gizmo_draw_preset_circle(const wmGizmo *gz,
const float mat[4][4],
int axis,
int select_id);
/* -------------------------------------------------------------------- */
/* 2D Button Gizmo */
/* `button2d_gizmo.cc` */
void ED_gizmo_button2d_group_background(const bContext *C, wmGizmoGroup *gzgroup);
/* -------------------------------------------------------------------- */
/* 3D Arrow Gizmo */
enum {
ED_GIZMO_ARROW_STYLE_NORMAL = 0,
ED_GIZMO_ARROW_STYLE_CROSS = 1,
ED_GIZMO_ARROW_STYLE_BOX = 2,
ED_GIZMO_ARROW_STYLE_CONE = 3,
ED_GIZMO_ARROW_STYLE_PLANE = 4,
};
/* transform */
enum {
/** Inverted offset during interaction - if set it also sets constrained below. */
ED_GIZMO_ARROW_XFORM_FLAG_INVERTED = (1 << 3),
/** Clamp arrow interaction to property width. */
ED_GIZMO_ARROW_XFORM_FLAG_CONSTRAINED = (1 << 4),
};
/* draw_options */
enum {
/* Show arrow stem. */
ED_GIZMO_ARROW_DRAW_FLAG_STEM = (1 << 0),
ED_GIZMO_ARROW_DRAW_FLAG_ORIGIN = (1 << 1),
};
/**
* Define a custom property UI range.
*
* \note Needs to be called before #WM_gizmo_target_property_def_rna!
*/
void ED_gizmo_arrow3d_set_ui_range(wmGizmo *gz, float min, float max);
/**
* Define a custom factor for arrow min/max distance.
*
* \note Needs to be called before #WM_gizmo_target_property_def_rna!
*/
void ED_gizmo_arrow3d_set_range_fac(wmGizmo *gz, float range_fac);
/* -------------------------------------------------------------------- */
/* Cage Gizmo */
enum {
ED_GIZMO_CAGE_XFORM_FLAG_TRANSLATE = (1 << 0), /* Translates */
ED_GIZMO_CAGE_XFORM_FLAG_ROTATE = (1 << 1), /* Rotates */
ED_GIZMO_CAGE_XFORM_FLAG_SCALE = (1 << 2), /* Scales */
ED_GIZMO_CAGE_XFORM_FLAG_SCALE_UNIFORM = (1 << 3), /* Scales uniformly */
ED_GIZMO_CAGE_XFORM_FLAG_SCALE_SIGNED = (1 << 4), /* Negative scale allowed */
};
/* draw_style */
enum {
/** Display the hover region (edge or corner) of the underlying bounding box. */
ED_GIZMO_CAGE2D_STYLE_BOX = 0,
/**
* Display the bounding box plus dots on four corners while hovering,
* usually used for transforming a 2D shape.
*/
ED_GIZMO_CAGE2D_STYLE_BOX_TRANSFORM,
/** Display the bounding circle while hovering. */
ED_GIZMO_CAGE2D_STYLE_CIRCLE,
};
enum {
ED_GIZMO_CAGE3D_STYLE_BOX = 0,
/* TODO: rename */
ED_GIZMO_CAGE3D_STYLE_CIRCLE = 1,
};
/* draw_options */
enum {
ED_GIZMO_CAGE_DRAW_FLAG_NOP = 0,
/** Draw a central handle (instead of having the entire area selectable)
* Needed for large rectangles that we don't want to swallow all events. */
ED_GIZMO_CAGE_DRAW_FLAG_XFORM_CENTER_HANDLE = (1 << 0),
ED_GIZMO_CAGE_DRAW_FLAG_CORNER_HANDLES = (1 << 1),
};
/** #wmGizmo.highlight_part */
enum {
ED_GIZMO_CAGE2D_PART_TRANSLATE = 0,
ED_GIZMO_CAGE2D_PART_SCALE,
/* Edges */
ED_GIZMO_CAGE2D_PART_SCALE_MIN_X,
ED_GIZMO_CAGE2D_PART_SCALE_MAX_X,
ED_GIZMO_CAGE2D_PART_SCALE_MIN_Y,
ED_GIZMO_CAGE2D_PART_SCALE_MAX_Y,
/* Corners */
ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MIN_Y,
ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MAX_Y,
ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MIN_Y,
ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MAX_Y,
ED_GIZMO_CAGE2D_PART_ROTATE,
};
/** #wmGizmo.highlight_part */
enum {
/* ordered min/mid/max so we can loop over values (MIN/MID/MAX) on each axis. */
ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MIN_Z = 0,
ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MID_Z,
ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MAX_Z,
ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MID_Y_MIN_Z,
ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MID_Y_MID_Z,
ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MID_Y_MAX_Z,
ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MAX_Y_MIN_Z,
ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MAX_Y_MID_Z,
ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MAX_Y_MAX_Z,
ED_GIZMO_CAGE3D_PART_SCALE_MID_X_MIN_Y_MIN_Z,
ED_GIZMO_CAGE3D_PART_SCALE_MID_X_MIN_Y_MID_Z,
ED_GIZMO_CAGE3D_PART_SCALE_MID_X_MIN_Y_MAX_Z,
ED_GIZMO_CAGE3D_PART_SCALE_MID_X_MID_Y_MIN_Z,
ED_GIZMO_CAGE3D_PART_SCALE_MID_X_MID_Y_MID_Z,
ED_GIZMO_CAGE3D_PART_SCALE_MID_X_MID_Y_MAX_Z,
ED_GIZMO_CAGE3D_PART_SCALE_MID_X_MAX_Y_MIN_Z,
ED_GIZMO_CAGE3D_PART_SCALE_MID_X_MAX_Y_MID_Z,
ED_GIZMO_CAGE3D_PART_SCALE_MID_X_MAX_Y_MAX_Z,
ED_GIZMO_CAGE3D_PART_SCALE_MAX_X_MIN_Y_MIN_Z,
ED_GIZMO_CAGE3D_PART_SCALE_MAX_X_MIN_Y_MID_Z,
ED_GIZMO_CAGE3D_PART_SCALE_MAX_X_MIN_Y_MAX_Z,
ED_GIZMO_CAGE3D_PART_SCALE_MAX_X_MID_Y_MIN_Z,
ED_GIZMO_CAGE3D_PART_SCALE_MAX_X_MID_Y_MID_Z,
ED_GIZMO_CAGE3D_PART_SCALE_MAX_X_MID_Y_MAX_Z,
ED_GIZMO_CAGE3D_PART_SCALE_MAX_X_MAX_Y_MIN_Z,
ED_GIZMO_CAGE3D_PART_SCALE_MAX_X_MAX_Y_MID_Z,
ED_GIZMO_CAGE3D_PART_SCALE_MAX_X_MAX_Y_MAX_Z,
ED_GIZMO_CAGE3D_PART_TRANSLATE,
ED_GIZMO_CAGE3D_PART_ROTATE,
};
/* -------------------------------------------------------------------- */
/* Dial Gizmo */
/* draw_options */
enum {
ED_GIZMO_DIAL_DRAW_FLAG_NOP = 0,
ED_GIZMO_DIAL_DRAW_FLAG_CLIP = (1 << 0),
ED_GIZMO_DIAL_DRAW_FLAG_FILL = (1 << 1),
ED_GIZMO_DIAL_DRAW_FLAG_FILL_SELECT = (1 << 2),
ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_MIRROR = (1 << 3),
ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_START_Y = (1 << 4),
/* Always show the angle value as an arc in the dial. */
ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_VALUE = (1 << 5),
};
/* -------------------------------------------------------------------- */
/* Move Gizmo */
/* draw_options */
enum {
ED_GIZMO_MOVE_DRAW_FLAG_NOP = 0,
/* only for solid shapes */
ED_GIZMO_MOVE_DRAW_FLAG_FILL = (1 << 0),
ED_GIZMO_MOVE_DRAW_FLAG_FILL_SELECT = (1 << 1),
ED_GIZMO_MOVE_DRAW_FLAG_ALIGN_VIEW = (1 << 2),
};
enum {
ED_GIZMO_MOVE_STYLE_RING_2D = 0,
ED_GIZMO_MOVE_STYLE_CROSS_2D = 1,
};
/* -------------------------------------------------------------------- */
/* Button Gizmo */
enum {
ED_GIZMO_BUTTON_SHOW_OUTLINE = (1 << 0),
ED_GIZMO_BUTTON_SHOW_BACKDROP = (1 << 1),
/**
* Draw a line from the origin to the offset (similar to an arrow)
* sometimes needed to show what the button edits.
*/
ED_GIZMO_BUTTON_SHOW_HELPLINE = (1 << 2),
};
/* -------------------------------------------------------------------- */
/* Primitive Gizmo */
enum {
ED_GIZMO_PRIMITIVE_STYLE_PLANE = 0,
ED_GIZMO_PRIMITIVE_STYLE_CIRCLE,
ED_GIZMO_PRIMITIVE_STYLE_ANNULUS,
};
/* -------------------------------------------------------------------- */
/* Specific gizmos utils */
/* `snap3d_gizmo.cc` */
ed::transform::SnapObjectContext *ED_gizmotypes_snap_3d_context_ensure(Scene *scene, wmGizmo *gz);
void ED_gizmotypes_snap_3d_flag_set(wmGizmo *gz, int flag);
bool ED_gizmotypes_snap_3d_is_enabled(const wmGizmo *gz);
void ED_gizmotypes_snap_3d_data_get(const bContext *C,
wmGizmo *gz,
float r_loc[3],
float r_nor[3],
int r_elem_index[3],
eSnapMode *r_snap_elem);
} // namespace blender

View File

@@ -0,0 +1,30 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*
* \name Generic Gizmo Utilities.
*/
#pragma once
namespace blender {
struct bContext;
struct wmGizmoGroupType;
/** Wrapper function (operator name can't be guessed). */
bool ED_gizmo_poll_or_unlink_delayed_from_operator(const bContext *C,
wmGizmoGroupType *gzgt,
const char *idname);
bool ED_gizmo_poll_or_unlink_delayed_from_tool_ex(const bContext *C,
wmGizmoGroupType *gzgt,
const char *gzgt_idname);
/** Use this as poll function directly for: #wmGizmoGroupType.poll */
bool ED_gizmo_poll_or_unlink_delayed_from_tool(const bContext *C, wmGizmoGroupType *gzgt);
} // namespace blender

View File

@@ -0,0 +1,242 @@
/* SPDX-FileCopyrightText: 2008 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
#include "DNA_listBase.h"
struct Depsgraph;
struct SnapObjectContext;
namespace blender {
struct ID;
struct PointerRNA;
struct Brush;
struct CfraElem;
struct GP_SpaceConversion;
struct bGPDframe;
struct bGPDlayer;
struct bGPDspoint;
struct bGPDstroke;
struct bGPdata;
struct tGPspoint;
struct ARegion;
struct Main;
struct RegionView3D;
struct ReportList;
struct Scene;
struct ScrArea;
struct ToolSettings;
struct View3D;
struct bContext;
struct Material;
struct Object;
struct KeyframeEditData;
struct bAnimContext;
struct wmKeyConfig;
struct wmOperator;
/* ------------- Grease-Pencil Runtime Data ---------------- */
/**
* Temporary 'Stroke Point' data (2D / screen-space)
*
* Used as part of the 'stroke cache' used during drawing of new strokes
*/
struct tGPspoint {
/** Coordinates x and y of cursor (in relative to area). */
float m_xy[2];
/** Pressure of tablet at this point. */
float pressure;
/** Pressure of tablet at this point for alpha factor. */
float strength;
/** Time relative to stroke start (used when converting to path & in build modifier). */
float time;
/** Factor of uv along the stroke. */
float uv_fac;
/** UV rotation for dot mode. */
float uv_rot;
/** Random value. */
float rnd[3];
/** Random flag. */
bool rnd_dirty;
/** Point vertex color. */
float vert_color[4];
};
/* ----------- Grease Pencil Tools/Context ------------- */
/* Context-dependent */
/**
* Get the active Grease Pencil data-block
* \note This is the original (#G.main) copy of the data-block, stored in files.
* Do not use for reading evaluated copies of GP Objects data.
*/
bGPdata *ED_annotation_data_get_active(const bContext *C);
/**
* Get pointer to active Grease Pencil data-block,
* and an RNA-pointer to trace back to whatever owns it.
*/
bGPdata **ED_annotation_data_get_pointers(const bContext *C, PointerRNA *r_ptr);
/**
* Get pointer to active Grease Pencil data-block for annotations,
* and an RNA-pointer to trace back to whatever owns it,
* when context info is not available.
*/
bGPdata **ED_annotation_data_get_pointers_direct(ID *screen_id,
ScrArea *area,
Scene *scene,
PointerRNA *r_ptr);
/**
* Get the active Grease Pencil data-block, when context is not available.
*/
bGPdata *ED_annotation_data_get_active_direct(ID *screen_id, ScrArea *area, Scene *scene);
/**
* Check whether given stroke can be edited given the supplied context.
* TODO: do we need additional flags for screen-space vs data-space?.
*/
bool ED_gpencil_stroke_can_use_direct(const ScrArea *area, const bGPDstroke *gps);
/* ----------- Grease Pencil Operators ----------------- */
void ED_keymap_gpencil_legacy(wmKeyConfig *keyconf);
void ED_operatortypes_gpencil_legacy();
/* ------------ Grease-Pencil Drawing API ------------------ */
/* `drawgpencil.cc` */
/**
* Draw grease-pencil sketches to specified 2d-view that uses `ibuf` corrections.
*/
void ED_annotation_draw_2dimage(const bContext *C);
/**
* Draw grease-pencil sketches to specified 2d-view
* assuming that matrices are already set correctly.
*
* \note This gets called twice - first time with onlyv2d=true to draw 'canvas' strokes,
* second time with onlyv2d=false for screen-aligned strokes.
*/
void ED_annotation_draw_view2d(const bContext *C, bool onlyv2d);
/**
* Draw annotations sketches to specified 3d-view assuming that matrices are already set correctly.
* NOTE: this gets called twice - first time with only3d=true to draw 3d-strokes,
* second time with only3d=false for screen-aligned strokes.
*/
void ED_annotation_draw_view3d(
Scene *scene, Depsgraph *depsgraph, View3D *v3d, ARegion *region, bool only3d);
void ED_annotation_draw_ex(
Scene *scene, bGPdata *gpd, int winx, int winy, int cfra, char spacetype);
/* ----------- Grease-Pencil AnimEdit API ------------------ */
/**
* Loops over the GP-frames for a GP-layer, and applies the given callback.
*/
bool ED_gpencil_layer_frames_looper(bGPDlayer *gpl,
Scene *scene,
bool (*gpf_cb)(bGPDframe *, Scene *));
/**
* Make a listing all the gp-frames in a layer as cfraelems.
*/
void ED_gpencil_layer_make_cfra_list(bGPDlayer *gpl, ListBaseT<CfraElem> *elems, bool onlysel);
/**
* Check if one of the frames in this layer is selected.
*/
bool ED_gpencil_layer_frame_select_check(const bGPDlayer *gpl);
/**
* Set all/none/invert select.
*/
void ED_gpencil_layer_frame_select_set(bGPDlayer *gpl, short mode);
/**
* Select the frames in this layer that occur within the bounds specified.
*/
void ED_gpencil_layer_frames_select_box(bGPDlayer *gpl, float min, float max, short select_mode);
/**
* Select the frames in this layer that occur within the lasso/circle region specified.
*/
void ED_gpencil_layer_frames_select_region(KeyframeEditData *ked,
bGPDlayer *gpl,
short tool,
short select_mode);
/**
* Set all/none/invert select (like above, but with SELECT_* modes).
*/
void ED_gpencil_select_frames(bGPDlayer *gpl, short select_mode);
/**
* Select the frame in this layer that occurs on this frame (there should only be one at most).
*/
void ED_gpencil_select_frame(bGPDlayer *gpl, int selx, short select_mode);
/**
* Set the layer's channel as active
*/
void ED_gpencil_set_active_channel(bGPdata *gpd, bGPDlayer *gpl);
/**
* Delete selected frames.
*/
bool ED_gpencil_layer_frames_delete(bGPDlayer *gpl);
/**
* Duplicate selected frames from given gp-layer.
*/
void ED_gpencil_layer_frames_duplicate(bGPDlayer *gpl);
/**
* Set keyframe type for selected frames from given gp-layer
*
* \param type: The type of keyframe (#eBezTriple_KeyframeType) to set selected frames to.
*/
void ED_gpencil_layer_frames_keytype_set(bGPDlayer *gpl, short type);
/**
* Snap selected frames to ....
*/
void ED_gpencil_layer_snap_frames(bGPDlayer *gpl, Scene *scene, short mode);
/**
* Mirror selected gp-frames on...
* TODO: mirror over a specific time.
*/
void ED_gpencil_layer_mirror_frames(bGPDlayer *gpl, Scene *scene, short mode);
/**
* This function frees any allocated copy/paste buffer data.
*/
void ED_gpencil_anim_copybuf_free();
/**
* This function adds data to the copy/paste buffer, freeing existing data first
* Only the selected GP-layers get their selected keyframes copied.
*
* Returns whether the copy operation was successful or not.
*/
bool ED_gpencil_anim_copybuf_copy(bAnimContext *ac);
/**
* Pastes keyframes from buffer, and reports success.
*/
bool ED_gpencil_anim_copybuf_paste(bAnimContext *ac, short offset_mode);
/* ----------- Add Primitive Utilities -------------- */
/* texture coordinate utilities */
/**
* Ensure the #tGPspoint buffer (while drawing stroke)
* size is enough to save all points of the stroke.
*/
tGPspoint *ED_gpencil_sbuffer_ensure(tGPspoint *buffer_array,
int *buffer_size,
int *buffer_used,
bool clear);
} // namespace blender

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,21 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
#include "BLI_string_ref.hh"
namespace blender {
struct ID;
struct Main;
/** Handle complex user-facing ID renaming behavior, including user feedback (reporting). */
bool ED_id_rename(Main &bmain, ID &id, StringRefNull name);
} // namespace blender

View File

@@ -0,0 +1,248 @@
/* SPDX-FileCopyrightText: 2008 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
#include "DNA_listBase.h"
#include "DNA_space_types.h"
#include "BLI_string_ref.hh"
namespace blender {
struct ARegion;
struct ImBuf;
struct Image;
struct ImageUser;
struct Main;
struct ReportList;
struct Scene;
struct SpaceImage;
struct View2D;
struct bContext;
struct Paint;
struct wmOperator;
struct wmWindowManager;
/* `image_draw.cc` */
float ED_space_image_zoom_level(const View2D *v2d, int grid_dimension);
void ED_space_image_grid_steps(SpaceImage *sima,
float grid_steps_x[SI_GRID_STEPS_LEN],
float grid_steps_y[SI_GRID_STEPS_LEN],
int grid_dimension);
/**
* Calculate the increment snapping value for UV/image editor based on the zoom factor
* The code in here (except the offset part) is used in `grid_frag.glsl` (see `grid_res`) for
* drawing the grid overlay for the UV/Image editor.
*/
float ED_space_image_increment_snap_value(int grid_dimensions,
const float grid_steps[SI_GRID_STEPS_LEN],
float zoom_factor);
/* `image_edit.cc`, exported for transform. */
Image *ED_space_image(const SpaceImage *sima);
void ED_space_image_set(Main *bmain, SpaceImage *sima, Image *ima, bool automatic);
void ED_space_image_sync(Main *bmain, Image *image, bool ignore_render_viewer);
void ED_space_image_auto_set(const bContext *C, SpaceImage *sima);
Mask *ED_space_image_get_mask(const SpaceImage *sima);
void ED_space_image_set_mask(bContext *C, SpaceImage *sima, Mask *mask);
/**
* Returns mouse position in image space.
*/
bool ED_space_image_get_position(SpaceImage *sima,
ARegion *region,
const int mval[2],
float r_fpos[2]);
/**
* Returns color in linear space, matching #ED_space_node_color_sample().
*/
bool ED_space_image_color_sample(
SpaceImage *sima, ARegion *region, const int mval[2], float r_col[3], bool *r_is_data);
/* Acquires the image buffer of the given tile of the image in the given space. See the info on the
* BKE_image_acquire_ibuf function for information on the lock. Also see the image_acquire_ibuf
* function for the ensure_host_buffer argument. */
ImBuf *ED_space_image_acquire_buffer(SpaceImage *sima,
void **r_lock,
int tile,
const bool ensure_host_buffer);
/**
* Get the #SpaceImage flag that is valid for the given ibuf.
*/
int ED_space_image_get_display_channel_mask(ImBuf *ibuf);
void ED_space_image_release_buffer(SpaceImage *sima, ImBuf *ibuf, void *lock);
bool ED_space_image_has_buffer(SpaceImage *sima);
void ED_space_image_get_size(SpaceImage *sima, int *r_width, int *r_height);
void ED_space_image_get_size_fl(SpaceImage *sima, float r_size[2]);
void ED_space_image_get_aspect(SpaceImage *sima, float *r_aspx, float *r_aspy);
void ED_space_image_get_zoom(SpaceImage *sima,
const ARegion *region,
float *r_zoomx,
float *r_zoomy);
void ED_space_image_get_uv_aspect(SpaceImage *sima, float *r_aspx, float *r_aspy);
void ED_space_image_scopes_update(const bContext *C,
SpaceImage *sima,
ImBuf *ibuf,
bool use_view_settings);
/**
* Enable the paint cursor if it isn't already.
*
* purpose is to make sure the paint cursor is shown if paint mode is enabled in the image editor.
* The paint poll will ensure that the cursor is hidden when not in paint mode.
*/
void ED_space_image_paint_update(Main *bmain, wmWindowManager *wm, Scene *scene);
void ED_image_get_uv_aspect(Image *ima, ImageUser *iuser, float *r_aspx, float *r_aspy);
/** Takes `event->mval`. */
void ED_image_mouse_pos(SpaceImage *sima, const ARegion *region, const int mval[2], float co[2]);
void ED_image_view_center_to_point(SpaceImage *sima, float x, float y);
void ED_image_point_pos(
SpaceImage *sima, const ARegion *region, float x, float y, float *r_x, float *r_y);
void ED_image_point_pos__reverse(SpaceImage *sima,
const ARegion *region,
const float co[2],
float r_co[2]);
/**
* This is more a user-level functionality, for going to `next/prev` used slot,
* Stepping onto the last unused slot too.
*/
bool ED_image_slot_cycle(Image *image, int direction);
bool ED_space_image_show_render(const SpaceImage *sima);
bool ED_space_image_show_paint(const SpaceImage *sima);
bool ED_space_image_show_mask(const SpaceImage *sima);
bool ED_space_image_show_uvedit(const SpaceImage *sima, Object *obedit);
bool ED_space_image_paint_curve(const bContext *C);
/**
* Matches clip function.
*/
bool ED_space_image_check_show_maskedit(SpaceImage *sima, Object *obedit);
/**
* Returns true when the following conditions are met:
* - Current space is Image Editor.
* - The image editor is not a UV Editor.
* - It is set to Mask mode.
*
* It is not required to have mask opened for editing.
*/
bool ED_space_image_maskedit_poll(bContext *C);
/**
* Returns true when the following conditions are met:
* - Current space is Image Editor.
* - The image editor is not a UV Editor.
* - It is set to Mask mode.
* - Mask has visible and editable splines.
*
* It is not required to have mask opened for editing.
*/
bool ED_space_image_maskedit_visible_splines_poll(bContext *C);
/**
* Returns true when the following conditions are met:
* - Current space is Image Editor.
* - The image editor is not an UV Editor.
* - It is set to Mask mode.
* - The space has mask opened.
*/
bool ED_space_image_maskedit_mask_poll(bContext *C);
/**
* Returns true when the following conditions are met:
* - Current space is Image Editor.
* - The image editor is not an UV Editor.
* - It is set to Mask mode.
* - The space has mask opened.
* - Mask has visible and editable splines.
*/
bool ED_space_image_maskedit_mask_visible_splines_poll(bContext *C);
bool ED_space_image_cursor_poll(bContext *C);
bool ED_space_image_region_cursor_poll(bContext *C);
/**
* Used by node view too.
*/
void ED_image_draw_info(Scene *scene,
ARegion *region,
bool color_manage,
bool use_default_view,
int channels,
int x,
int y,
const unsigned char cp[4],
const float fp[4],
const float linearcol[4]);
bool ED_space_image_show_cache(const SpaceImage *sima);
bool ED_space_image_show_cache_and_mval_over(const SpaceImage *sima,
ARegion *region,
const int mval[2]);
bool ED_image_should_save_modified(const Main *bmain);
int ED_image_save_all_modified_info(const Main *bmain, ReportList *reports);
bool ED_image_save_all_modified(const bContext *C, ReportList *reports);
void ED_image_internal_autosave_flush(const Main *bmain);
/* `image_sequence.cc` */
struct ImageFrame;
struct ImageFrameRange {
ImageFrameRange *next, *prev;
/**
* File path of the first file in the range.
* May be relative to `G_MAIN->filepath` or the `root_path`
* passed in by #ED_image_filesel_detect_sequences.
*/
char filepath[FILE_MAX];
/* Sequence parameters. */
int length; /* Does not include placeholders, stops at gaps in sequence. */
int offset;
int max_framenr; /* Allows for calculating length including placeholders. */
/* UDIM tiles. */
bool udims_detected;
ListBaseT<LinkData> udim_tiles;
/* Temporary data. */
ListBaseT<ImageFrame> frames;
};
struct ImageFrame {
ImageFrame *next, *prev;
int framenr;
};
/**
* Used for both images and volume file loading.
*
* \param blendfile_path: For relative paths, the operator paths will be relative to this.
* \param root_path: When `op` references a relative path, #ImageFrameRange::filepath
* will be made relative to this path if possible, otherwise it will be made absolute.
* Note that `blendfile_path` may equal `root_path`, otherwise `root_path` may be set
* to a libraries absolute file-path.
*/
ListBaseT<ImageFrameRange> ED_image_filesel_detect_sequences(StringRefNull blendfile_path,
StringRefNull root_path,
wmOperator *op,
bool detect_udim);
bool ED_image_tools_paint_poll(bContext *C);
void ED_paint_cursor_start(Paint *paint, bool (*poll)(bContext *C));
} // namespace blender

View File

@@ -0,0 +1,45 @@
/* SPDX-FileCopyrightText: 2009 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
namespace blender {
struct Main;
struct Scene;
struct View3D;
struct ViewLayer;
struct wmWindowManager;
/* `info_stats.cc` */
void ED_info_stats_clear(wmWindowManager *wm, ViewLayer *view_layer);
const char *ED_info_statusbar_string_ex(Main *bmain,
Scene *scene,
ViewLayer *view_layer,
const char statusbar_flag);
const char *ED_info_statusbar_string(Main *bmain, Scene *scene, ViewLayer *view_layer);
const char *ED_info_statistics_string(Main *bmain, Scene *scene, ViewLayer *view_layer);
void ED_view3d_local_stats_free(View3D *v3d);
/**
* \param v3d_local: Pass this argument to calculate view-port local statistics.
* Note that this must only be used for local-view, otherwise report specific statistics
* will be written into the global scene statistics giving incorrect results.
*/
void ED_info_draw_stats(Main *bmain,
Scene *scene,
ViewLayer *view_layer,
View3D *v3d_local,
int x,
int *y,
int height);
} // namespace blender

View File

@@ -0,0 +1,163 @@
/* SPDX-FileCopyrightText: 2009 Blender Authors, Joshua Leung. All rights reserved.
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
#include "BLI_sys_types.h"
#include "DNA_curve_types.h"
#include "ED_anim_api.hh"
#include "ED_keyframes_keylist.hh"
namespace blender {
struct AnimData;
struct ChannelDrawList;
struct FCurve;
struct MaskLayer;
struct Object;
struct Scene;
struct View2D;
struct bAction;
struct bActionGroup;
struct bAnimContext;
struct bDopeSheet;
struct bGPDlayer;
struct GreasePencil;
struct GreasePencilLayer;
struct GreasePencilLayerTreeGroup;
/**
* Draw simple diamond-shape keyframe.
*
* The caller should set up vertex format, bind #GPU_SHADER_KEYFRAME_SHAPE,
* `immBegin(GPU_PRIM_POINTS, n)`, then call this `n` times.
*/
struct KeyframeShaderBindings {
uint pos_id;
uint size_id;
uint color_id;
uint outline_color_id;
uint flags_id;
};
void draw_keyframe_shape(float x,
float y,
float size,
bool sel,
eBezTriple_KeyframeType key_type,
eKeyframeShapeDrawOpts mode,
float alpha,
const KeyframeShaderBindings *sh_bindings,
short handle_type,
short extreme_type);
/* ******************************* Methods ****************************** */
/* Channel Drawing ------------------ */
/* F-Curve */
void ED_add_fcurve_channel(ChannelDrawList *channel_list,
bAnimListElem *ale,
FCurve *fcu,
float ypos,
float yscale_fac,
int saction_flag);
/* Action Group Summary */
void ED_add_action_group_channel(ChannelDrawList *channel_list,
bAnimListElem *ale,
bActionGroup *agrp,
float ypos,
float yscale_fac,
int saction_flag);
/* Layered Action Summary. */
void ED_add_action_layered_channel(ChannelDrawList *channel_list,
bAnimContext *ac,
bAnimListElem *ale,
bAction *action,
const float ypos,
const float yscale_fac,
int saction_flag);
/* Action Slot summary. */
void ED_add_action_slot_channel(ChannelDrawList *channel_list,
bAnimContext *ac,
bAnimListElem *ale,
animrig::Action &action,
animrig::Slot &slot,
float ypos,
float yscale_fac,
int saction_flag);
/* Object Summary */
void ED_add_object_channel(ChannelDrawList *channel_list,
bDopeSheet *ads,
Object *ob,
float ypos,
float yscale_fac,
int saction_flag);
/* Scene Summary */
void ED_add_scene_channel(ChannelDrawList *channel_list,
bDopeSheet *ads,
Scene *sce,
float ypos,
float yscale_fac,
int saction_flag);
/* DopeSheet Summary */
void ED_add_summary_channel(ChannelDrawList *channel_list,
bAnimContext *ac,
float ypos,
float yscale_fac,
int saction_flag);
/* Grease Pencil cels channels */
void ED_add_grease_pencil_cels_channel(ChannelDrawList *channel_list,
bDopeSheet *ads,
const GreasePencilLayer *layer,
float ypos,
float yscale_fac,
int saction_flag);
/* Grease Pencil layer group channels */
void ED_add_grease_pencil_layer_group_channel(ChannelDrawList *channel_list,
bDopeSheet *ads,
const GreasePencilLayerTreeGroup *layer_group,
float ypos,
float yscale_fac,
int saction_flag);
/* Grease Pencil data channels */
void ED_add_grease_pencil_datablock_channel(ChannelDrawList *channel_list,
bAnimContext *ac,
bAnimListElem *ale,
const GreasePencil *grease_pencil,
const float ypos,
const float yscale_fac,
int saction_flag);
/* Grease Pencil Layer */
void ED_add_grease_pencil_layer_legacy_channel(ChannelDrawList *channel_list,
bDopeSheet *ads,
bGPDlayer *gpl,
float ypos,
float yscale_fac,
int saction_flag);
/* Mask Layer */
void ED_add_mask_layer_channel(ChannelDrawList *channel_list,
bDopeSheet *ads,
MaskLayer *masklay,
float ypos,
float yscale_fac,
int saction_flag);
ChannelDrawList *ED_channel_draw_list_create();
void ED_channel_list_flush(ChannelDrawList *channel_list, View2D *v2d);
void ED_channel_list_free(ChannelDrawList *channel_list);
} // namespace blender

View File

@@ -0,0 +1,558 @@
/* SPDX-FileCopyrightText: 2008 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
#include "BLI_array.hh"
#include "BLI_enum_flags.hh"
#include "BLI_math_vector_types.hh"
#include "ED_anim_api.hh" /* for enum eAnimFilter_Flags */
#include "DNA_curve_types.h"
#include "DNA_listBase.h"
namespace blender {
struct BezTriple;
struct ButterworthCoefficients;
struct FCurve;
struct Scene;
struct bAnimContext;
struct bAnimListElem;
struct bDopeSheet;
/* ************************************************ */
/* Common Macros and Defines */
/* -------------------------------------------------------------------- */
/** \name Tool Flags
* \{ */
/** bezt validation. */
enum eEditKeyframes_Validate {
/* Frame range */
BEZT_OK_FRAME = 1,
BEZT_OK_FRAMERANGE,
/* Selection status (any of f1, f2, f3) */
BEZT_OK_SELECTED,
/* Selection status (f2 is enough) */
BEZT_OK_SELECTED_KEY,
/* Values (y-val) only */
BEZT_OK_VALUE,
BEZT_OK_VALUERANGE,
/* For graph editor keyframes (2D tests) */
BEZT_OK_REGION,
BEZT_OK_REGION_LASSO,
BEZT_OK_REGION_CIRCLE,
/* Only for keyframes a certain Dope-sheet channel. */
BEZT_OK_CHANNEL_LASSO,
BEZT_OK_CHANNEL_CIRCLE,
};
/** \} */
/* select modes */
enum eEditKeyframes_Select {
/* SELECT_SUBTRACT for all, followed by SELECT_ADD for some */
SELECT_REPLACE = (1 << 0),
/* add ok keyframes to selection */
SELECT_ADD = (1 << 1),
/* remove ok keyframes from selection */
SELECT_SUBTRACT = (1 << 2),
/* flip ok status of keyframes based on key status */
SELECT_INVERT = (1 << 3),
SELECT_EXTEND_RANGE = (1 << 4),
};
/* "selection map" building modes. */
enum eEditKeyframes_SelMap {
SELMAP_MORE = 0,
SELMAP_LESS,
};
/* snapping tools */
enum eEditKeyframes_Snap {
SNAP_KEYS_CURFRAME = 1,
SNAP_KEYS_NEARFRAME,
SNAP_KEYS_NEARSEC,
SNAP_KEYS_NEARMARKER,
SNAP_KEYS_HORIZONTAL,
SNAP_KEYS_VALUE,
SNAP_KEYS_TIME,
};
/* equalizing tools */
enum eEditKeyframes_Equalize {
EQUALIZE_HANDLES_LEFT = (1 << 0),
EQUALIZE_HANDLES_RIGHT = (1 << 1),
EQUALIZE_HANDLES_BOTH = (EQUALIZE_HANDLES_LEFT | EQUALIZE_HANDLES_RIGHT),
};
/* mirroring tools */
enum eEditKeyframes_Mirror {
MIRROR_KEYS_CURFRAME = 1,
MIRROR_KEYS_YAXIS,
MIRROR_KEYS_XAXIS,
MIRROR_KEYS_MARKER,
MIRROR_KEYS_VALUE,
MIRROR_KEYS_TIME,
};
/* use with BEZT_OK_REGION_LASSO */
struct KeyframeEdit_LassoData {
rctf *rectf_scaled;
const rctf *rectf_view;
Array<int2> mcoords;
};
/* use with BEZT_OK_REGION_CIRCLE */
struct KeyframeEdit_CircleData {
rctf *rectf_scaled;
const rctf *rectf_view;
float mval[2];
float radius_squared;
};
/* ************************************************ */
/* Non-Destructive Editing API (keyframes_edit.cc) */
/* -------------------------------------------------------------------- */
/** \name Defines for 'OK' polls + KeyframeEditData Flags
* \{ */
/* which verts of a keyframe is active (after polling) */
enum eKeyframeVertOk {
KEYFRAME_NONE = 0,
/* 'key' itself is ok */
KEYFRAME_OK_KEY = (1 << 0),
/* 'handle 1' is ok */
KEYFRAME_OK_H1 = (1 << 1),
/* 'handle 2' is ok */
KEYFRAME_OK_H2 = (1 << 2),
/* all flags */
KEYFRAME_OK_ALL = (KEYFRAME_OK_KEY | KEYFRAME_OK_H1 | KEYFRAME_OK_H2),
};
/* Flags for use during iteration */
enum eKeyframeIterFlags {
/* Consider handles in addition to key itself. Used in #keyframe_ok_checks, #select_bezier_add,
* #select_bezier_subtract. If set, treat key and handles separately (e.g (de)select them
* individually, and do additional visibility checks on the handles if necessary), otherwise
* always treat key and handles the same (e.g. (de)select all of them).
*/
KEYFRAME_ITER_INCL_HANDLES = (1 << 0),
/* Perform NLA time remapping (global -> strip) for the "f1" parameter
* (e.g. used for selection tools on summary tracks)
*/
KED_F1_NLA_UNMAP = (1 << 1),
/* Perform NLA time remapping (global -> strip) for the "f2" parameter */
KED_F2_NLA_UNMAP = (1 << 2),
/* Set this when handles aren't visible by default and you want to perform additional checks to
* get the actual visibility state. E.g. in some cases handles are only drawn if either a handle
* or their control point is selected. The selection state will have to be checked in the
* iterator callbacks then. */
/* Represents "Only Selected Keyframes" option (SIPO_SELVHANDLESONLY). */
KEYFRAME_ITER_HANDLES_DEFAULT_INVISIBLE = (1 << 3),
/* Represents "Show Handles" option (SIPO_NOHANDLES). */
KEYFRAME_ITER_HANDLES_INVISIBLE = (1 << 4),
};
ENUM_OPERATORS(eKeyframeIterFlags)
/** \} */
/* -------------------------------------------------------------------- */
/** \name Generic Properties for Keyframe Edit Tools
* \{ */
/**
* Temporary struct used to store frame time and selection status.
* Used for example by `columnselect_action_keys` to select all keyframes in a column.
*/
struct CfraElem {
CfraElem *next, *prev;
/* Expected to be in global scene time (e.g. not NLA unmapped). */
float cfra;
int sel;
};
struct KeyframeEditData {
/* generic properties/data access */
/** temp list for storing custom list of data to check */
ListBaseT<CfraElem> cfra_elem_list;
ListBaseT<TimeMarker> time_marker_list;
/** pointer to current scene - many tools need access to cfra/etc. */
Scene *scene;
/** pointer to custom data - usually 'Object' but also 'rectf', but could be other types too */
void *data;
/** storage of times/values as 'decimals' */
float f1, f2;
/** storage of times/values/flags as 'whole' numbers */
int i1, i2;
/* current iteration data */
/** F-Curve that is being iterated over */
FCurve *fcu;
/** index of current keyframe being iterated over */
int curIndex;
/** Y-position of midpoint of the channel (for the dope-sheet). */
float channel_y;
/* flags */
/** current flags for the keyframe we're reached in the iteration process */
eKeyframeVertOk curflags;
/** settings for iteration process */
eKeyframeIterFlags iterflags;
};
/** \} */
/* -------------------------------------------------------------------- */
/** \name Function Pointer Typedefs
* \{ */
/** Callback function that refreshes the F-Curve after use. */
using FcuEditFunc = void (*)(FCurve &fcu);
/** Callback function that operates on the given #BezTriple. */
using KeyframeEditFunc = short (*)(KeyframeEditData *ked, BezTriple *bezt);
/** \} */
/* -------------------------------------------------------------------- */
/** \name Custom Data Type Defines
* \{ */
/** Custom data for remapping one range to another in a fixed way. */
struct KeyframeEditCD_Remap {
float oldMin, oldMax; /* old range */
float newMin, newMax; /* new range */
};
/** Paste options. */
enum eKeyPasteOffset {
/** Paste keys starting at current frame. */
KEYFRAME_PASTE_OFFSET_CFRA_START,
/** Paste keys ending at current frame. */
KEYFRAME_PASTE_OFFSET_CFRA_END,
/** Paste keys relative to the current frame when copying. */
KEYFRAME_PASTE_OFFSET_CFRA_RELATIVE,
/** Paste keys from original time. */
KEYFRAME_PASTE_OFFSET_NONE,
};
enum eKeyPasteValueOffset {
/** Paste keys with the first key matching the key left of the cursor. */
KEYFRAME_PASTE_VALUE_OFFSET_LEFT_KEY,
/** Paste keys with the last key matching the key right of the cursor. */
KEYFRAME_PASTE_VALUE_OFFSET_RIGHT_KEY,
/** Paste keys relative to the value of the curve under the cursor. */
KEYFRAME_PASTE_VALUE_OFFSET_CFRA,
/** Paste values relative to the cursor position. */
KEYFRAME_PASTE_VALUE_OFFSET_CURSOR,
/** Paste keys with the exact copied value. */
KEYFRAME_PASTE_VALUE_OFFSET_NONE,
};
enum eKeyMergeMode {
/** Overlay existing with new keys. */
KEYFRAME_PASTE_MERGE_MIX,
/** Replace entire fcurve. */
KEYFRAME_PASTE_MERGE_OVER,
/** Overwrite keys in pasted range. */
KEYFRAME_PASTE_MERGE_OVER_RANGE,
/** Overwrite keys in pasted range (use all keyframe start & end for range). */
KEYFRAME_PASTE_MERGE_OVER_RANGE_ALL,
};
/** Possible errors occurring while pasting keys. */
enum eKeyPasteError {
/** No errors occurred. */
KEYFRAME_PASTE_OK,
/** Nothing was copied. */
KEYFRAME_PASTE_NOTHING_TO_PASTE,
/** No F-curves was selected to paste into. */
KEYFRAME_PASTE_NOWHERE_TO_PASTE
};
/** \} */
/* -------------------------------------------------------------------- */
/** \name Looping API
*
* Functions for looping over keyframes.
* \{ */
/**
* This function is used to loop over BezTriples in the given F-Curve, applying a given
* operation on them, and optionally applies an F-Curve validation function afterwards.
*
* function for working with F-Curve data only
* (i.e. when filters have been chosen to explicitly use this).
*/
short ANIM_fcurve_keyframes_loop(KeyframeEditData *ked,
FCurve *fcu,
KeyframeEditFunc key_ok,
KeyframeEditFunc key_cb,
FcuEditFunc fcu_cb);
/**
* Sets selected keyframes' bezier handles to an equal length and optionally makes
* the keyframes' handles horizontal.
* \param handle_length: Desired handle length, must be positive.
* \param flatten: Makes the keyframes' handles the same value as the keyframe,
* flattening the curve at that point.
*/
void ANIM_fcurve_equalize_keyframes_loop(FCurve *fcu,
eEditKeyframes_Equalize mode,
float handle_length,
bool flatten);
/**
* Function for working with any type (i.e. one of the known types) of animation channel.
*/
short ANIM_animchannel_keyframes_loop(KeyframeEditData *ked,
bDopeSheet *ads,
bAnimListElem *ale,
KeyframeEditFunc key_ok,
KeyframeEditFunc key_cb,
FcuEditFunc fcu_cb);
/**
* Calls callback_fn() for each keyframe in each fcurve in the filtered animation context.
* Assumes the callback updates keys.
*/
void ANIM_animdata_keyframe_callback(bAnimContext *ac,
eAnimFilter_Flags filter,
KeyframeEditFunc callback_fn);
/**
* Functions for making sure all keyframes are in good order.
*/
void ANIM_editkeyframes_refresh(bAnimContext *ac);
/** \} */
/* -------------------------------------------------------------------- */
/** \name BezTriple Callback Getters
* \{ */
/* accessories */
KeyframeEditFunc ANIM_editkeyframes_ok(short mode);
/* edit */
KeyframeEditFunc ANIM_editkeyframes_snap(short mode);
/**
* \note for markers and 'value', the values to use must be supplied as the first float value.
*/
KeyframeEditFunc ANIM_editkeyframes_mirror(short mode);
KeyframeEditFunc ANIM_editkeyframes_select(eEditKeyframes_Select selectmode);
/**
* Set all selected Bezier Handles to a single type.
*/
KeyframeEditFunc ANIM_editkeyframes_handles(short mode);
/**
* Set the interpolation type of the selected BezTriples in each F-Curve to the specified one.
*/
KeyframeEditFunc ANIM_editkeyframes_ipo(short mode);
KeyframeEditFunc ANIM_editkeyframes_keytype(eBezTriple_KeyframeType keyframe_type);
KeyframeEditFunc ANIM_editkeyframes_easing(short mode);
/** \} */
/* -------------------------------------------------------------------- */
/** \name BezTriple Callbacks (Selection Map)
* \{ */
/**
* Get a callback to populate the selection settings map
* requires: `ked->custom = char[]` of length `fcurve->totvert`.
*/
KeyframeEditFunc ANIM_editkeyframes_buildselmap(short mode);
/**
* Change the selection status of the keyframe based on the map entry for this vert
* requires: `ked->custom = char[]` of length `fcurve->totvert`.
*/
short bezt_selmap_flush(KeyframeEditData *ked, BezTriple *bezt);
/** \} */
/* -------------------------------------------------------------------- */
/** \name BezTriple Callback (Assorted Utilities)
* \{ */
/**
* Used to calculate the average location of all relevant BezTriples by summing their locations.
*/
short bezt_calc_average(KeyframeEditData *ked, BezTriple *bezt);
/**
* Used to extract a set of cfra-elems from the keyframes.
*/
short bezt_to_cfraelem(KeyframeEditData *ked, BezTriple *bezt);
/**
* Used to remap times from one range to another.
* requires: `ked->custom = KeyframeEditCD_Remap`.
*/
void bezt_remap_times(KeyframeEditData *ked, BezTriple *bezt);
/** \} */
/* -------------------------------------------------------------------- */
/** \name 1.5-D Region Testing Utilities (Lasso/Circle Select)
* \{ */
/* XXX: These are temporary,
* until we can unify GP/Mask Keyframe handling and standard FCurve Keyframe handling */
bool keyframe_region_lasso_test(const KeyframeEdit_LassoData *data_lasso, const float xy[2]);
bool keyframe_region_circle_test(const KeyframeEdit_CircleData *data_circle, const float xy[2]);
/* ************************************************ */
/* Destructive Editing API `keyframes_general.cc`. */
bool duplicate_fcurve_keys(FCurve *fcu);
float get_default_rna_value(const FCurve *fcu, PropertyRNA *prop, PointerRNA *ptr);
struct FCurveSegment {
FCurveSegment *next, *prev;
int start_index, length;
};
/**
* Return a list of #FCurveSegment with a start index and a length.
* A segment is a continuous selection of keyframes.
* Keys that have BEZT_FLAG_IGNORE_TAG set are treated as unselected.
* The caller is responsible for freeing the memory.
*/
ListBaseT<FCurveSegment> find_fcurve_segments(FCurve *fcu);
void clean_fcurve(bAnimListElem *ale, float thresh, bool cleardefault, bool only_selected_keys);
void blend_to_neighbor_fcurve_segment(FCurve *fcu, FCurveSegment *segment, float factor);
void breakdown_fcurve_segment(FCurve *fcu, FCurveSegment *segment, float factor);
void scale_average_fcurve_segment(FCurve *fcu, FCurveSegment *segment, float factor);
void push_pull_fcurve_segment(FCurve *fcu, FCurveSegment *segment, float factor);
/** Used for operators that need a reference key of the segment to work. */
enum class FCurveSegmentAnchor { LEFT, RIGHT };
void scale_from_fcurve_segment_neighbor(FCurve *fcu,
FCurveSegment *segment,
float factor,
FCurveSegmentAnchor anchor);
/**
* Get a 1D gauss kernel. Since the kernel is symmetrical, only calculates the positive side.
* \param sigma: The shape of the gauss distribution.
* \param kernel_size: How long the kernel array is.
*/
void ED_ANIM_get_1d_gauss_kernel(const float sigma, int kernel_size, double *r_kernel);
ButterworthCoefficients *ED_anim_allocate_butterworth_coefficients(const int filter_order);
void ED_anim_free_butterworth_coefficients(ButterworthCoefficients *bw_coeff);
void ED_anim_calculate_butterworth_coefficients(float cutoff_frequency,
float sampling_frequency,
ButterworthCoefficients *bw_coeff);
/**
* \param samples: Are expected to start at the first frame of the segment with a buffer of size
* `segment->filter_order` at the left.
*/
void butterworth_smooth_fcurve_segment(FCurve *fcu,
FCurveSegment *segment,
float *samples,
int sample_count,
float factor,
int blend_in_out,
int sample_rate,
ButterworthCoefficients *bw_coeff);
void smooth_fcurve_segment(FCurve *fcu,
FCurveSegment *segment,
const float *original_values,
float *samples,
const int sample_count,
float factor,
int kernel_size,
const double *kernel);
/**
* Snap the keys on the given FCurve segment to an S-Curve. By modifying the `factor` the part of
* the S-Curve that the keys are snapped to is moved on the x-axis.
*/
void ease_fcurve_segment(FCurve *fcu, FCurveSegment *segment, float factor, float width);
enum tShearDirection {
SHEAR_FROM_LEFT = 1,
SHEAR_FROM_RIGHT,
};
void shear_fcurve_segment(FCurve *fcu,
FCurveSegment *segment,
float factor,
tShearDirection direction);
/**
* Shift the FCurve segment up/down so that it aligns with the key before/after
* the segment.
*
* \param factor: blend factor from -1.0 to 1.0. The sign determines whether the
* segment is aligned with the key before or after the segment.
*/
void blend_offset_fcurve_segment(FCurve *fcu, FCurveSegment *segment, float factor);
void blend_to_ease_fcurve_segment(FCurve *fcu, FCurveSegment *segment, float factor);
void time_offset_fcurve_segment(FCurve *fcu, FCurveSegment *segment, float frame_offset);
bool decimate_fcurve(bAnimListElem *ale, float remove_ratio, float error_sq_max);
bool match_slope_fcurve_segment(FCurve *fcu, FCurveSegment *segment, float factor);
/**
* Blends the selected keyframes to the default value of the property the F-curve drives.
*/
void blend_to_default_fcurve(PointerRNA *id_ptr, FCurve *fcu, float factor);
/**
* Use a weighted moving-means method to reduce intensity of fluctuations.
*/
void smooth_fcurve(FCurve *fcu);
/* ----------- */
/**
* Clear the copy-paste buffer.
*
* Normally this is not necessary, as `copy_animedit_keys()` will do this for
* you.
*/
void ANIM_fcurves_copybuf_reset();
/**
* Free the copy-paste buffer.
*/
void ANIM_fcurves_copybuf_free();
/**
* Copy animation keys into the copy buffer.
*
* \returns Whether anything was copied into the buffer.
*/
bool copy_animedit_keys(bAnimContext *ac, ListBaseT<bAnimListElem> *anim_data);
struct KeyframePasteContext {
eKeyPasteOffset offset_mode;
eKeyPasteValueOffset value_offset_mode;
eKeyMergeMode merge_mode;
bool flip;
int num_slots_selected; /* Number of selected Action Slots to paste into. */
int num_fcurves_selected; /* Number of selected F-Curves to paste into. */
};
eKeyPasteError paste_animedit_keys(bAnimContext *ac,
ListBaseT<bAnimListElem> *anim_data,
const KeyframePasteContext &paste_context);
/* ************************************************ */
/** \} */
} // namespace blender

View File

@@ -0,0 +1,292 @@
/* SPDX-FileCopyrightText: 2009 Blender Authors, Joshua Leung. All rights reserved.
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
#include "BLI_bounds_types.hh"
#include "BLI_math_vector_types.hh"
#include "DNA_curve_types.h"
#include "DNA_listBase.h"
#include "ANIM_action.hh"
namespace blender {
struct AnimData;
struct CacheFile;
struct FCurve;
struct GreasePencil;
struct GreasePencilLayer;
struct GreasePencilLayerTreeGroup;
struct MaskLayer;
struct Object;
struct Scene;
struct Strip;
struct bAction;
struct bActionGroup;
struct bAnimContext;
struct bDopeSheet;
struct bGPDlayer;
struct bGPdata;
namespace animrig {
class Action;
class Slot;
} // namespace animrig
/* ****************************** Base Structs ****************************** */
struct AnimKeylist;
/** Information about the stretch of time from current to the next column. */
struct ActKeyBlockInfo {
/** Combination of flags from all curves. */
short flag;
/** Mask of flags that differ between curves. */
short conflict;
/** Selection flag. */
char sel;
};
/** Keyframe Column Struct. */
struct ActKeyColumn {
/* ListBaseT linkage */
ActKeyColumn *next, *prev;
/* sorting-tree linkage */
/** 'children' of this node, less than and greater than it (respectively) */
ActKeyColumn *left, *right;
/** parent of this node in the tree */
ActKeyColumn *parent;
/* keyframe info */
eBezTriple_KeyframeType key_type;
/** eKeyframeHandleDrawOpts */
char handle_type;
/** eKeyframeExtremeDrawOpts */
char extreme_type;
short sel;
float cfra;
/* key-block info */
ActKeyBlockInfo block;
/* number of curves and keys in this column */
short totcurve, totkey, totblock;
};
/** #ActKeyBlockInfo - Flag. */
enum eActKeyBlock_Hold {
/** Key block represents a moving hold. */
ACTKEYBLOCK_FLAG_MOVING_HOLD = (1 << 0),
/** Key block represents a static hold */
ACTKEYBLOCK_FLAG_STATIC_HOLD = (1 << 1),
/** Key block represents any kind of hold. */
ACTKEYBLOCK_FLAG_ANY_HOLD = (1 << 2),
/** The block is grease pencil. */
ACTKEYBLOCK_FLAG_GPENCIL = (1 << 4),
/** The curve segment uses linear interpolation. */
ACTKEYBLOCK_FLAG_IPO_LINEAR = (1 << 5),
/** The curve segment uses constant interpolation. */
ACTKEYBLOCK_FLAG_IPO_CONSTANT = (1 << 6),
/** The curve segment uses easing or dynamic interpolation. */
ACTKEYBLOCK_FLAG_IPO_OTHER = (1 << 7),
};
/* *********************** Keyframe Drawing ****************************** */
/** Options for keyframe shape drawing. */
enum eKeyframeShapeDrawOpts {
/* only the border */
KEYFRAME_SHAPE_FRAME = 0,
/* only the inside filling */
KEYFRAME_SHAPE_INSIDE,
/* the whole thing */
KEYFRAME_SHAPE_BOTH,
};
/** Handle type. */
enum eKeyframeHandleDrawOpts {
/* Don't draw */
KEYFRAME_HANDLE_NONE = 0,
/* Various marks in order of increasing display priority. */
KEYFRAME_HANDLE_AUTO_CLAMP,
KEYFRAME_HANDLE_AUTO,
KEYFRAME_HANDLE_VECTOR,
KEYFRAME_HANDLE_ALIGNED,
KEYFRAME_HANDLE_FREE,
};
/** Extreme type. */
enum eKeyframeExtremeDrawOpts {
KEYFRAME_EXTREME_NONE = 0,
/** Minimum present. */
KEYFRAME_EXTREME_MIN = (1 << 0),
/** Maximum present. */
KEYFRAME_EXTREME_MAX = (1 << 1),
/** Grouped keys have different states. */
KEYFRAME_EXTREME_MIXED = (1 << 2),
/** Both neighbors are equal to this key. */
KEYFRAME_EXTREME_FLAT = (1 << 3),
};
/* ******************************* Methods ****************************** */
AnimKeylist *ED_keylist_create();
void ED_keylist_free(AnimKeylist *keylist);
void ED_keylist_prepare_for_direct_access(AnimKeylist *keylist);
const ActKeyColumn *ED_keylist_find_exact(const AnimKeylist *keylist, float cfra);
const ActKeyColumn *ED_keylist_find_next(const AnimKeylist *keylist, float cfra);
const ActKeyColumn *ED_keylist_find_prev(const AnimKeylist *keylist, float cfra);
const ActKeyColumn *ED_keylist_find_closest(const AnimKeylist *keylist, float cfra);
const ActKeyColumn *ED_keylist_find_any_between(const AnimKeylist *keylist,
const Bounds<float> frame_range);
bool ED_keylist_is_empty(const AnimKeylist *keylist);
const ListBaseT<ActKeyColumn> *ED_keylist_listbase(const AnimKeylist *keylist);
bool ED_keylist_all_keys_frame_range(const AnimKeylist *keylist, Bounds<float> *r_frame_range);
/**
* Return the selected key-frame's range. If none are selected, return False and
* do not affect the frame range.
*/
bool ED_keylist_selected_keys_frame_range(const AnimKeylist *keylist,
Bounds<float> *r_frame_range);
const ActKeyColumn *ED_keylist_array(const AnimKeylist *keylist);
int64_t ED_keylist_array_len(const AnimKeylist *keylist);
/* Key-data Generation --------------- */
/**
* Add the keyframes of the F-Curve to the keylist.
*
* \param adt: the AnimData associated with the FCurve, if any. Must be
* non-null if `use_nla_remapping` is true, because it's needed for that
* remapping.
* \param range: adds keys in the given range to the keylist plus 1 extra on
* each side if available.
* \param use_nla_remapping: whether to allow NLA remapping or not. `true` by
* default, basically only `false` when this F-Curve is an NLA control curve
* (like animated influence) or a driver.
*/
void fcurve_to_keylist(AnimData *adt,
FCurve *fcu,
AnimKeylist *keylist,
int saction_flag,
float2 range,
bool use_nla_remapping);
/* Action Group */
void action_group_to_keylist(
AnimData *adt, bActionGroup *agrp, AnimKeylist *keylist, int saction_flag, float2 range);
/* Action */
/**
* Generate a full list of the keys in `dna_action` that are within the frame
* range `range`.
*
* For layered actions, this is limited to the keys that are for the slot
* assigned to `adt`.
*
* Note: this should only be used in places that need or want the *full* list of
* keys, without any filtering by e.g. channel selection/visibility, etc. For
* use cases that need such filtering, use `action_slot_summary_to_keylist()`
* instead.
*
* \see action_slot_summary_to_keylist()
*/
void action_to_keylist(
AnimData *adt, bAction *dna_action, AnimKeylist *keylist, int saction_flag, float2 range);
/* Object */
void ob_to_keylist(
bDopeSheet *ads, Object *ob, AnimKeylist *keylist, int saction_flag, float2 range);
/* Cache File */
void cachefile_to_keylist(bDopeSheet *ads,
CacheFile *cache_file,
AnimKeylist *keylist,
int saction_flag);
/* Scene */
void scene_to_keylist(
bDopeSheet *ads, Scene *sce, AnimKeylist *keylist, int saction_flag, float2 range);
/* DopeSheet Summary */
void summary_to_keylist(bAnimContext *ac, AnimKeylist *keylist, int saction_flag, float2 range);
/**
* Generate a summary channel keylist for the specified slot, merging it into
* `keylist`.
*
* This filters the keys to be consistent with the visible channels in the
* editor indicated by `ac`
*
* \param animated_id: the particular animated ID that the slot summary is being
* generated for. This is needed for filtering channels based on bone selection,
* etc. NOTE: despite being passed as a pointer, this should never be null. It's
* currently passed as a pointer to be defensive because I (Nathan) am not 100%
* confident at the time of writing (PR #134922) that the callers of this
* actually guarantee a non-null pointer (they should, but bugs). This way we
* can assert internally to catch if that ever happens.
*
* \param action: the action containing the slot to generate the summary for.
*
* \param slot_handle: the handle of the slot to generate the summary for.
*
* \param keylist: the keylist that the generated summary will be merged into.
*
* \param saction_flag: needed for the `SACTION_SHOW_EXTREMES` flag, to
* determine whether to compute and store the data needed to determine which
* keys are "extremes" (local maxima/minima).
*
* \param range: only keys within this time range will be included in the
* summary.
*/
void action_slot_summary_to_keylist(bAnimContext *ac,
ID *animated_id,
animrig::Action &action,
animrig::slot_handle_t slot_handle,
AnimKeylist *keylist,
int /* eSAction_Flag */ saction_flag,
float2 range);
/* Grease Pencil datablock summary (Legacy) */
void gpencil_to_keylist(bDopeSheet *ads, bGPdata *gpd, AnimKeylist *keylist, bool active);
/* Grease Pencil Cels. */
void grease_pencil_cels_to_keylist(AnimData *adt,
const GreasePencilLayer *gpl,
AnimKeylist *keylist,
int saction_flag);
/* Grease Pencil Layer Group. */
void grease_pencil_layer_group_to_keylist(AnimData *adt,
const GreasePencilLayerTreeGroup *layer_group,
AnimKeylist *keylist,
const int saction_flag);
/* Grease Pencil Data-Block. */
void grease_pencil_data_block_to_keylist(AnimData *adt,
const GreasePencil *grease_pencil,
AnimKeylist *keylist,
const int saction_flag,
bool active_layer_only);
/* Grease Pencil Layer (Legacy) */
void gpl_to_keylist(bDopeSheet *ads, bGPDlayer *gpl, AnimKeylist *keylist);
/* Mask */
void mask_to_keylist(bDopeSheet *ads, MaskLayer *masklay, AnimKeylist *keylist);
/* Sequencer strip data. */
void sequencer_strip_to_keylist(const Strip &strip, AnimKeylist &keylist, Scene &scene);
/* ActKeyColumn API ---------------- */
/** Checks if #ActKeyColumn has any block data. */
bool actkeyblock_is_valid(const ActKeyColumn *ac);
/** Checks if #ActKeyColumn can be used as a block (i.e. drawn/used to detect "holds"). */
int actkeyblock_get_valid_hold(const ActKeyColumn *ac);
} // namespace blender

View File

@@ -0,0 +1,307 @@
/* SPDX-FileCopyrightText: 2008 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
#include "DNA_anim_types.h"
#include "RNA_types.hh"
namespace blender {
struct ID;
struct Main;
struct Scene;
struct KeyingSet;
struct AnimationEvalContext;
struct FCurve;
struct ReportList;
struct bContext;
struct EnumPropertyItem;
struct PointerRNA;
struct PropertyRNA;
namespace animrig {
enum class ModifyKeyReturn;
enum class ModifyKeyMode;
} // namespace animrig
/* -------------------------------------------------------------------- */
/** \name Key-Framing Management
* \{ */
/**
* \brief Lesser Key-framing API call.
*
* Update integer/discrete flags of the FCurve (used when creating/inserting keyframes,
* but also through RNA when editing an ID prop, see #37103).
*/
void update_autoflags_fcurve(FCurve *fcu, bContext *C, ReportList *reports, PointerRNA *ptr);
/* -------- */
/**
* Add the given number of keyframes to the FCurve. Their coordinates are
* uninitialized, so the curve should not be used without further attention.
*
* The newly created keys are selected, existing keys are not touched.
*
* This can be used to allocate all the keys at once, and then update them
* afterwards.
*/
void ED_keyframes_add(FCurve *fcu, int num_keys_to_add);
/** \} */
/* -------------------------------------------------------------------- */
/** \name Keying Sets
* \{ */
/**
* Get the index of the Keying Set provided, for the given Scene.
*/
int ANIM_scene_get_keyingset_index(Scene *scene, KeyingSet *keyingset);
void ANIM_keyingset_visit_for_search(const bContext *C,
PointerRNA *ptr,
PropertyRNA *prop,
const char *edit_text,
FunctionRef<void(StringPropertySearchVisitParams)> visit_fn);
void ANIM_keyingset_visit_for_search_no_poll(
const bContext *C,
PointerRNA *ptr,
PropertyRNA *prop,
const char *edit_text,
FunctionRef<void(StringPropertySearchVisitParams)> visit_fn);
/**
* Dynamically populate an enum of Keying Sets.
*/
const EnumPropertyItem *ANIM_keying_sets_enum_itemf(bContext *C,
PointerRNA *ptr,
PropertyRNA *prop,
bool *r_free);
/**
* Get the keying set from enum values generated in #ANIM_keying_sets_enum_itemf.
*
* Type is the Keying Set the user specified to use when calling the operator:
* \param type:
* - == 0: use scene's active Keying Set.
* - > 0: use a user-defined Keying Set from the active scene.
* - < 0: use a builtin Keying Set.
*/
KeyingSet *ANIM_keyingset_get_from_enum_type(Scene *scene, int type);
KeyingSet *ANIM_keyingset_get_from_idname(Scene *scene, const char *idname);
/**
* Check if #KeyingSet can be used in the current context.
*/
bool ANIM_keyingset_context_ok_poll(bContext *C, KeyingSet *keyingset);
/** \} */
/* -------------------------------------------------------------------- */
/** \name Drivers
* \{ */
/** Flags for use by driver creation calls */
enum eCreateDriverFlags {
/** create drivers with a default variable for nicer UI */
CREATEDRIVER_WITH_DEFAULT_DVAR = (1 << 0),
};
/** Heuristic to use for connecting target properties to driven ones */
enum eCreateDriver_MappingTypes {
/** 1 to Many - Use the specified index, and drive all elements with it */
CREATEDRIVER_MAPPING_1_N = 0,
/** 1 to 1 - Only for the specified index on each side */
CREATEDRIVER_MAPPING_1_1 = 1,
/** Many to Many - Match up the indices one by one (only for drivers on vectors/arrays) */
CREATEDRIVER_MAPPING_N_N = 2,
/** None (Single Prop):
* Do not create driver with any targets; these will get added later instead */
CREATEDRIVER_MAPPING_NONE = 3,
/** None (All Properties):
* Do not create driver with any targets; these will get added later instead */
CREATEDRIVER_MAPPING_NONE_ALL = 4,
};
/**
* Mapping Types enum for operators.
* \note Used by #ANIM_OT_driver_button_add and #UI_OT_eyedropper_driver.
*/
extern const EnumPropertyItem prop_driver_create_mapping_types[];
/* -------- */
enum eDriverFCurveCreationMode {
/** Don't add anything if not found. */
DRIVER_FCURVE_LOOKUP_ONLY = 0,
/** Add with keyframes, for visual tweaking. */
DRIVER_FCURVE_KEYFRAMES = 1,
/** Add without data, for pasting. */
DRIVER_FCURVE_EMPTY = 3
};
/**
* Get (or add relevant data to be able to do so) F-Curve from the driver stack,
* for the given Animation Data block. This assumes that all the destinations are valid.
*
* \note This low-level function shouldn't be used directly for most tools,
* although there are special cases where this approach is preferable.
*/
FCurve *verify_driver_fcurve(ID *id,
const char rna_path[],
int array_index,
eDriverFCurveCreationMode creation_mode);
FCurve *alloc_driver_fcurve(const char rna_path[],
int array_index,
eDriverFCurveCreationMode creation_mode);
/* -------- */
/**
* \brief Main Driver Management API calls
*
* Add a new driver for the specified property on the given ID block,
* and make it be driven by the specified target.
*
* This is intended to be used in conjunction with a modal "eyedropper"
* for picking the variable that is going to be used to drive this one.
*
* \param flag: eCreateDriverFlags
* \param driver_type: eDriver_Types
* \param mapping_type: eCreateDriver_MappingTypes
*/
int ANIM_add_driver_with_target(ReportList *reports,
ID *dst_id,
const char dst_path[],
int dst_index,
ID *src_id,
const char src_path[],
int src_index,
short flag,
eDriver_Types driver_type,
short mapping_type);
/* -------- */
/**
* \brief Main Driver Management API calls.
*
* Add a new driver for the specified property on the given ID block
*
* \param flag: is of type #eCreateDriverFlags. Passing the flag as 0 is also an option which will
* create a driver without a variable.
*/
int ANIM_add_driver(ReportList *reports,
ID *id,
const char rna_path[],
int array_index,
short flag,
eDriver_Types type);
/**
* \brief Main Driver Management API calls.
*
* Remove the driver for the specified property on the given ID block.
*
* \return Whether any driver was removed.
*/
bool ANIM_remove_driver(ID *id, const char rna_path[], int array_index);
/* -------- */
/**
* Clear copy-paste buffer for drivers.
* \note This function frees any allocated copy/paste buffer data.
*/
void ANIM_drivers_copybuf_free();
/**
* Clear copy-paste buffer for driver variable sets.
* \note This function frees any allocated copy/paste buffer data.
*/
void ANIM_driver_vars_copybuf_free();
/* -------- */
/**
* Returns whether there is a driver in the copy/paste buffer to paste.
*/
bool ANIM_driver_can_paste();
/**
* \brief Main Driver Management API calls.
*
* Make a copy of the driver for the specified property on the given ID block.
*/
bool ANIM_copy_driver(
ReportList *reports, ID *id, const char rna_path[], int array_index, short flag);
/**
* \brief Main Driver Management API calls.
*
* Add a new driver for the specified property on the given ID block or replace an existing one
* with the driver + driver-curve data from the buffer.
*/
bool ANIM_paste_driver(
ReportList *reports, ID *id, const char rna_path[], int array_index, short flag);
/* -------- */
/**
* Checks if there are driver variables in the copy/paste buffer.
*/
bool ANIM_driver_vars_can_paste();
/**
* Copy the given driver's variables to the buffer.
*/
bool ANIM_driver_vars_copy(ReportList *reports, FCurve *fcu);
/**
* Paste the variables in the buffer to the given FCurve.
*/
bool ANIM_driver_vars_paste(ReportList *reports, FCurve *fcu, bool replace);
/* -------- */
/**
* Create a driver & variable that reads the specified property,
* and store it in the buffers for Paste Driver and Paste Variables.
*/
void ANIM_copy_as_driver(ID *target_id, const char *target_path, const char *var_name);
/** \} */
/* -------------------------------------------------------------------- */
/** \name Keyframe Checking
* \{ */
/**
* \brief Lesser Keyframe Checking API call.
*
* - Returns whether the current value of a given property differs from the interpolated value.
* - Used for button drawing.
*/
bool fcurve_is_changed(PointerRNA ptr,
PropertyRNA *prop,
FCurve *fcu,
const AnimationEvalContext *anim_eval_context);
/** \} */
} // namespace blender

View File

@@ -0,0 +1,43 @@
/* SPDX-FileCopyrightText: 2008 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
namespace blender {
struct bContext;
struct KeyBlock;
struct Lattice;
struct Object;
struct SelectPick_Params;
struct UndoType;
struct wmKeyConfig;
/* `lattice_ops.cc` */
void ED_operatortypes_lattice();
void ED_keymap_lattice(wmKeyConfig *keyconf);
KeyBlock *ED_lattice_get_edit_shape_key(const Lattice *latt);
/* `editlattice_select.cc` */
bool ED_lattice_flags_set(Object *obedit, int flag);
/**
* \return True when pick finds an element or the selection changed.
*/
bool ED_lattice_select_pick(bContext *C, const int mval[2], const SelectPick_Params &params);
bool ED_lattice_deselect_all_multi(bContext *C);
/* `editlattice_undo.cc` */
/** Export for ED_undo_sys. */
void ED_lattice_undosys_type(UndoType *ut);
} // namespace blender

View File

@@ -0,0 +1,139 @@
/* SPDX-FileCopyrightText: 2008 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
#include "DNA_listBase.h"
namespace blender {
struct Main;
struct Scene;
struct ScrArea;
struct TimeMarker;
struct bAnimContext;
struct bContext;
struct wmKeyConfig;
struct ARegion;
struct ViewLayer;
struct CfraElem;
/* -------------------------------------------------------------------- */
/** \name Drawing API
* \{ */
/** Flags for drawing markers. */
enum {
DRAW_MARKERS_LINES = (1 << 0),
DRAW_MARKERS_LOCAL = (1 << 1),
DRAW_MARKERS_MARGIN = (1 << 2),
};
/** Draw Scene-Markers in time window. */
void ED_markers_draw(const bContext *C, int flag);
/** \} */
/* -------------------------------------------------------------------- */
/** \name Backend API
* \{ */
/**
* Public API for getting markers from the scene & area.
*
* \return A #TimeMarker list.
*/
ListBaseT<TimeMarker> *ED_scene_markers_get(const bContext *C, Scene *scene);
/**
* Public API for getting markers from context.
*
* \return A #TimeMarker list.
*/
ListBaseT<TimeMarker> *ED_context_get_markers(const bContext *C);
ListBaseT<TimeMarker> *ED_sequencer_context_get_markers(const bContext *C);
ListBaseT<TimeMarker> *ED_scene_markers_get_from_area(const Main &bmain,
Scene *scene,
ViewLayer *view_layer,
const ScrArea *area);
/**
* Apply some transformation to markers after the fact
*
* \param markers: List of markers to affect - this may or may not be the scene markers list,
* so don't assume anything.
* \param scene: Current scene (for getting current frame)
* \param mode: (TfmMode) transform mode that this transform is for
* \param value: From the transform code, this is `t->vec[0]`
* (which is delta transform for grab/extend, and scale factor for scale)
* \param side: (B/L/R) for 'extend' functionality, which side of current frame to use
*/
int ED_markers_post_apply_transform(
ListBaseT<TimeMarker> *markers, Scene *scene, int mode, float value, char side);
/**
* \return the marker that is closest to `frame`.
* Non-empty `markers` is guaranteed to return a marker.
*
* \note For selecting, the caller is expected to exclude markers beyond a small threshold.
*/
TimeMarker *ED_markers_find_nearest_marker(ListBaseT<TimeMarker> *markers, float frame);
/**
* Return the time of the marker that occurs on a frame closest to the given time.
*/
int ED_markers_find_nearest_marker_time(ListBaseT<TimeMarker> *markers, float x);
void ED_markers_get_minmax(ListBaseT<TimeMarker> *markers,
short sel,
float *r_first,
float *r_last);
/**
* This function makes a list of all the markers. The only_sel
* argument is used to specify whether only the selected markers
* are added.
*/
void ED_markers_make_cfra_list(ListBaseT<TimeMarker> *markers,
ListBaseT<CfraElem> *lb,
bool only_selected);
void ED_markers_deselect_all(ListBaseT<TimeMarker> *markers, int action);
/**
* Get the first selected marker.
*/
TimeMarker *ED_markers_get_first_selected(ListBaseT<TimeMarker> *markers);
/**
* Returns true if the marker region is currently visible in the area.
*/
bool ED_markers_region_visible(const ScrArea *area, const ARegion *region);
/** \} */
/* -------------------------------------------------------------------- */
/** \name Operators
* \{ */
/**
* Called in `screen_ops.cc`, #ED_operatortypes_screen().
*/
void ED_operatortypes_marker();
/**
* Called in `screen_ops.cc`, #ED_keymap_screen().
*/
void ED_keymap_marker(wmKeyConfig *keyconf);
/**
* Debugging only: print debugging prints of list of markers.
*/
void debug_markers_print_list(ListBaseT<TimeMarker> *markers);
/** \} */
} // namespace blender

View File

@@ -0,0 +1,214 @@
/* SPDX-FileCopyrightText: 2012 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
#include "DNA_listBase.h"
#include "DNA_mask_types.h"
namespace blender {
struct ARegion;
struct CfraElem;
struct Depsgraph;
struct KeyframeEditData;
struct MaskLayer;
struct MaskLayerShape;
struct Scene;
struct ScrArea;
struct bContext;
struct wmKeyConfig;
/* `mask_edit.cc` */
/**
* Returns true when the following conditions are met:
* - Current space supports mask editing.
* - The space is configured to interact with mask.
*
* It is not required to have mask opened for editing.
*/
bool ED_maskedit_poll(bContext *C);
/**
* Returns true when the following conditions are met:
* - Current space supports mask editing.
* - The space is configured to interact with mask.
* - Mask has visible and editable splines.
*
* It is not required to have mask opened for editing.
*/
bool ED_maskedit_visible_splines_poll(bContext *C);
/**
* Returns true when the following conditions are met:
* - Current space supports mask editing.
* - The space is configured to interact with mask.
* - The space has mask open for editing.
*/
bool ED_maskedit_mask_poll(bContext *C);
/**
* Returns true when the following conditions are met:
* - Current space supports mask editing.
* - The space is configured to interact with mask.
* - The space has mask opened.
* - Mask has visible and editable splines.
*/
bool ED_maskedit_mask_visible_splines_poll(bContext *C);
void ED_mask_deselect_all(const bContext *C);
void ED_operatortypes_mask();
void ED_keymap_mask(wmKeyConfig *keyconf);
void ED_operatormacros_mask();
/* `mask_query.cc` */
void ED_mask_get_size(ScrArea *area, int *r_width, int *r_height);
void ED_mask_zoom(ScrArea *area, ARegion *region, float *r_zoomx, float *r_zoomy);
void ED_mask_get_aspect(ScrArea *area, ARegion *region, float *r_aspx, float *r_aspy);
void ED_mask_pixelspace_factor(ScrArea *area, ARegion *region, float *r_scalex, float *r_scaley);
/**
* Takes `event->mval`.
*/
void ED_mask_mouse_pos(ScrArea *area, ARegion *region, const int mval[2], float r_co[2]);
/**
* \param x, y: input, mval space.
* \param r_x, r_y: output, mask point space.
*/
void ED_mask_point_pos(ScrArea *area, ARegion *region, float x, float y, float *r_x, float *r_y);
void ED_mask_point_pos__reverse(
ScrArea *area, ARegion *region, float x, float y, float *r_x, float *r_y);
void ED_mask_cursor_location_get(ScrArea *area, float cursor[2]);
/**
* Calculate the bounding box of selected mask points.
*
* \param handles_as_knot: Selected handles contribute the knot position rather
* than their actual position. Individual handle selection is still evaluated.
* Useful for "view selected" where handles shouldn't extend bounds beyond the knot.
*
* \param handles_as_knot_selected_only: Any selection on the point contributes only the
* knot position. Individual handle selection is not evaluated.
* Useful for rotate/scale gizmo origins where the pivot should always be the knot.
*/
bool ED_mask_selected_minmax(const bContext *C,
float min[2],
float max[2],
bool handles_as_knot,
bool handles_as_knot_selected_only);
void ED_mask_center_from_pivot_ex(const bContext *C,
ScrArea *area,
char mode,
bool handles_as_knot_selected_only,
float r_center[2],
bool *r_has_select);
/* `mask_draw.cc` */
/**
* Sets up the opengl context.
* width, height are to match the values from #ED_mask_get_size().
*/
void ED_mask_draw_region(Depsgraph *depsgraph,
Mask *mask,
ARegion *region,
bool show_overlays,
MaskDrawFlag draw_flag,
MaskDrawType draw_type,
MaskOverlayMode overlay_mode,
float blend_factor,
int width_i,
int height_i,
float aspx,
float aspy,
bool do_scale_applied,
bool do_draw_cb,
float stabmat[4][4],
const bContext *C);
void ED_mask_draw_frames(Mask *mask, ARegion *region, int cfra, int sfra, int efra);
/* `mask_shapekey.cc` */
void ED_mask_layer_shape_auto_key(MaskLayer *mask_layer, int frame);
bool ED_mask_layer_shape_auto_key_all(Mask *mask, int frame);
bool ED_mask_layer_shape_auto_key_select(Mask *mask, int frame);
/* ----------- Mask AnimEdit API ------------------ */
/**
* Loops over the mask-frames for a mask-layer, and applies the given callback.
*/
bool ED_masklayer_frames_looper(MaskLayer *mask_layer,
Scene *scene,
bool (*mask_layer_shape_cb)(MaskLayerShape *, Scene *));
/**
* Make a listing all the mask-frames in a layer as cfraelems.
*/
void ED_masklayer_make_cfra_list(MaskLayer *mask_layer, ListBaseT<CfraElem> *elems, bool onlysel);
/**
* Check if one of the frames in this layer is selected.
*/
bool ED_masklayer_frame_select_check(const MaskLayer *mask_layer);
/**
* Set all/none/invert select.
*/
void ED_masklayer_frame_select_set(MaskLayer *mask_layer, short mode);
/**
* Select the frames in this layer that occur within the bounds specified.
*/
void ED_masklayer_frames_select_box(MaskLayer *mask_layer,
float min,
float max,
short select_mode);
/**
* Select the frames in this layer that occur within the lasso/circle region specified.
*/
void ED_masklayer_frames_select_region(KeyframeEditData *ked,
MaskLayer *mask_layer,
short tool,
short select_mode);
/**
* Set all/none/invert select (like above, but with SELECT_* modes).
*/
void ED_mask_select_frames(MaskLayer *mask_layer, short select_mode);
/**
* Select the frame in this layer that occurs on this frame (there should only be one at most).
*/
void ED_mask_select_frame(MaskLayer *mask_layer, int selx, short select_mode);
/**
* Delete selected frames.
*/
bool ED_masklayer_frames_delete(MaskLayer *mask_layer);
/**
* Duplicate selected frames from given mask-layer.
*/
bool ED_masklayer_frames_duplicate(MaskLayer *mask_layer);
/**
* Snap selected frames to ...
*/
void ED_masklayer_snap_frames(MaskLayer *mask_layer, Scene *scene, short mode);
#if 0
void free_gpcopybuf();
void copy_gpdata();
void paste_gpdata();
void mirror_masklayer_frames(MaskLayer *mask_layer, short mode);
#endif
} // namespace blender

View File

@@ -0,0 +1,68 @@
/* SPDX-FileCopyrightText: 2008 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
#include "BLI_span.hh"
namespace blender {
struct Base;
struct MetaElem;
struct Object;
struct SelectPick_Params;
struct UndoType;
struct bContext;
struct wmKeyConfig;
void ED_operatortypes_metaball();
void ED_operatormacros_metaball();
void ED_keymap_metaball(wmKeyConfig *keyconf);
/**
* Add meta-element primitive to meta-ball object (which is in edit mode).
*/
MetaElem *ED_mball_add_primitive(
bContext *C, Object *obedit, bool obedit_is_new, float mat[4][4], float dia, int type);
Base *ED_mball_base_and_elem_from_select_buffer(Span<Base *> bases,
const uint select_id,
MetaElem **r_ml);
/**
* Select meta-element with mouse click (user can select radius circle or stiffness circle).
*
* \return True when pick finds an element or the selection changed.
*/
bool ED_mball_select_pick(bContext *C, const int mval[2], const SelectPick_Params &params);
bool ED_mball_deselect_all_multi(bContext *C);
/**
* This function is used to free all MetaElems from MetaBall.
*/
void ED_mball_editmball_free(Object *obedit);
/**
* This function is called, when MetaBall Object is switched from object mode to edit mode.
*/
void ED_mball_editmball_make(Object *obedit);
/**
* This function is called, when MetaBall Object switched from edit mode to object mode.
* List of MetaElements is copied from `object->data->edit_elems` to `object->data->elems`.
*/
void ED_mball_editmball_load(Object *obedit);
/* `editmball_undo.cc` */
/** Export for ED_undo_sys. */
void ED_mball_undosys_type(UndoType *ut);
#define MBALLSEL_STIFF (1u << 30)
#define MBALLSEL_RADIUS (1u << 31)
#define MBALLSEL_ANY (MBALLSEL_STIFF | MBALLSEL_RADIUS)
} // namespace blender

View File

@@ -0,0 +1,667 @@
/* SPDX-FileCopyrightText: 2008 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
#include "BKE_attribute.hh"
#include "BLI_compiler_attrs.h"
#include "BLI_math_vector_types.hh"
#include "BLI_span.hh"
#include "BLI_virtual_array.hh"
#include "DNA_windowmanager_enums.h"
namespace blender {
struct ARegion;
struct BMBVHTree;
struct BMEdge;
struct BMEditMesh;
struct BMElem;
struct BMFace;
struct BMLoop;
struct BMVert;
struct BMesh;
struct BMeshNormalsUpdate_Params;
struct Base;
struct Depsgraph;
struct KeyBlock;
struct Main;
struct MDeformVert;
struct Mesh;
struct Object;
struct ReportList;
struct Scene;
struct SelectPick_Params;
struct UndoType;
struct UvMapVert;
struct UvVertMap;
struct View3D;
struct ViewContext;
struct bContext;
struct wmKeyConfig;
struct wmOperator;
struct UvElement;
struct UvElementMap;
/* `editmesh_utils.cc` */
class EditMeshSymmetryHelper {
public:
static std::optional<EditMeshSymmetryHelper> create_if_needed(Object *ob, uchar htype);
bool any_mirror_vert_selected(BMVert *v, char hflag) const;
bool any_mirror_edge_selected(BMEdge *e, char hflag) const;
bool any_mirror_face_selected(BMFace *f, char hflag) const;
void set_hflag_on_mirror_verts(BMVert *v, char hflag, bool value) const;
void set_hflag_on_mirror_edges(BMEdge *e, char hflag, bool value) const;
void set_hflag_on_mirror_faces(BMFace *f, char hflag, bool value) const;
void apply_on_mirror_verts(BMVert *v, FunctionRef<void(BMVert *)> op) const;
void apply_on_mirror_edges(BMEdge *e, FunctionRef<void(BMEdge *)> op) const;
void apply_on_mirror_faces(BMFace *f, FunctionRef<void(BMFace *)> op) const;
private:
EditMeshSymmetryHelper(Object *ob, uchar htype);
BMEditMesh *em_;
Mesh *mesh_;
uchar htype_;
bool use_topology_mirror_;
Map<BMVert *, Vector<BMVert *>> vert_to_mirror_map_;
Map<BMEdge *, Vector<BMEdge *>> edge_to_mirror_map_;
Map<BMFace *, Vector<BMFace *>> face_to_mirror_map_;
};
/**
* \param em: Edit-mesh used for generating mirror data.
* \param use_self: Allow a vertex to point to itself (middle verts).
* \param use_select: Restrict to selected verts.
* \param respecthide: Skip hidden vertices.
* \param use_topology: Use topology mirror.
* \param maxdist: Distance for close point test.
* \param r_index: Optional array to write into, as an alternative to a custom-data layer
* (length of total verts).
*/
void EDBM_verts_mirror_cache_begin_ex(BMEditMesh *em,
int axis,
bool use_self,
bool use_select,
bool respecthide,
bool use_topology,
float maxdist,
int *r_index);
void EDBM_verts_mirror_cache_begin(
BMEditMesh *em, int axis, bool use_self, bool use_select, bool respecthide, bool use_topology);
void EDBM_verts_mirror_apply(BMEditMesh *em, int sel_from, int sel_to);
BMVert *EDBM_verts_mirror_get(BMEditMesh *em, BMVert *v);
BMEdge *EDBM_verts_mirror_get_edge(BMEditMesh *em, BMEdge *e);
BMFace *EDBM_verts_mirror_get_face(BMEditMesh *em, BMFace *f);
void EDBM_verts_mirror_cache_clear(BMEditMesh *em, BMVert *v);
void EDBM_verts_mirror_cache_end(BMEditMesh *em);
void EDBM_mesh_normals_update_ex(BMEditMesh *em, const BMeshNormalsUpdate_Params *params);
void EDBM_mesh_normals_update(BMEditMesh *em);
void EDBM_selectmode_to_scene(bContext *C);
void EDBM_mesh_make(Object *ob, int select_mode, bool add_key_index);
/** Replaces the edit-mesh in the object with a new one based on the given mesh. */
void EDBM_mesh_make_from_mesh(Object *ob, Mesh *src_mesh, int select_mode, bool add_key_index);
/**
* Should only be called on the active edit-mesh, otherwise call #BKE_editmesh_free_data.
*/
void EDBM_mesh_free_data(BMEditMesh *em);
/**
* \warning This can invalidate the #Mesh runtime cache of other objects (for linked duplicates).
* Most callers should run #DEG_id_tag_update on `ob->data`, see: #46738, #46913.
* This ensures #BKE_object_free_derived_caches runs on all objects that use this mesh.
*/
void EDBM_mesh_load_ex(Main *bmain, Object *ob, bool free_data);
void EDBM_mesh_load(Main *bmain, Object *ob);
/**
* flushes based on the current select mode. If in vertex select mode,
* verts select/deselect edges and faces, if in edge select mode,
* edges select/deselect faces and vertices, and in face select mode faces select/deselect
* edges and vertices.
*/
void EDBM_select_more(BMEditMesh *em, bool use_face_step);
void EDBM_select_less(BMEditMesh *em, bool use_face_step);
void EDBM_selectmode_flush_ex(BMEditMesh *em, short selectmode);
void EDBM_selectmode_flush(BMEditMesh *em);
/**
* Mode independent selection/de-selection flush from vertices.
*
* \param select: When true, flush the selection state to de-selected elements,
* otherwise perform the opposite, flushing de-selection.
*/
void EDBM_select_flush_from_verts(BMEditMesh *em, bool select);
bool EDBM_vert_color_check(BMEditMesh *em);
/**
* Swap is 0 or 1, if 1 it hides not selected.
*/
bool EDBM_mesh_hide(BMEditMesh *em, bool swap);
bool EDBM_mesh_reveal(BMEditMesh *em, bool select);
struct EDBMUpdate_Params {
uint calc_looptris : 1;
uint calc_normals : 1;
uint is_destructive : 1;
};
/**
* So many tools call these that we better make it a generic function.
*/
void EDBM_update(Mesh *mesh, const EDBMUpdate_Params *params);
/**
* Bad level call from Python API.
*/
void EDBM_update_extern(Mesh *mesh, bool do_tessellation, bool is_destructive);
/**
* A specialized vert map used by stitch operator.
*/
UvElementMap *BM_uv_element_map_create(BMesh *bm,
const Scene *scene,
bool uv_selected,
bool use_winding,
bool use_seams,
bool do_islands);
void BM_uv_element_map_free(UvElementMap *element_map);
/**
* Return the #UvElement associated with a given #BMLoop, or NULL if no association exists.
*
* \param element_map: The #UvElementMap to look in.
* \param l: The loop to search for.
* \return The #UvElement associated with #l, or NULL if not found. (e.g. the vertex is hidden.)
*/
UvElement *BM_uv_element_get(const UvElementMap *element_map, const BMLoop *l);
UvElement *BM_uv_element_get_head(UvElementMap *element_map, UvElement *child);
int BM_uv_element_get_unique_index(UvElementMap *element_map, UvElement *child);
UvElement **BM_uv_element_map_ensure_head_table(UvElementMap *element_map);
int *BM_uv_element_map_ensure_unique_index(UvElementMap *element_map);
/**
* Can we edit UVs for this mesh?
*/
bool EDBM_uv_check(BMEditMesh *em);
/**
* last_sel, use em->act_face otherwise get the last selected face in the edit-selections
* at the moment, last_sel is mainly useful for making sure the space image doesn't flicker.
*/
BMFace *EDBM_uv_active_face_get(BMEditMesh *em, bool sloppy, bool selected);
void BM_uv_vert_map_free(UvVertMap *vmap);
UvMapVert *BM_uv_vert_map_at_index(UvVertMap *vmap, unsigned int v);
/**
* Return a new #UvVertMap from the edit-mesh.
*/
UvVertMap *BM_uv_vert_map_create(BMesh *bm, bool use_select, bool respect_hide);
void EDBM_flag_enable_all(BMEditMesh *em, char hflag);
void EDBM_flag_disable_all(BMEditMesh *em, char hflag);
/** \copydoc #BM_uvselect_clear */
bool EDBM_uvselect_clear(BMEditMesh *em);
bool BMBVH_EdgeVisible(const BMBVHTree *tree,
const BMEdge *e,
const Depsgraph *depsgraph,
const ARegion *region,
const View3D *v3d,
const Object *obedit);
void EDBM_project_snap_verts(
bContext *C, Depsgraph *depsgraph, ARegion *region, Object *obedit, BMEditMesh *em);
/* `editmesh_automerge.cc` */
/** \return true if a change is made. */
bool EDBM_automerge(Object *obedit, bool update, char hflag, float dist, bool use_centroid);
/** \return true if a change is made. */
bool EDBM_automerge_connected(Object *obedit, bool update, char hflag, float dist);
/** \return true if a change is made. */
bool EDBM_automerge_and_split(
Object *obedit, bool split_edges, bool split_faces, bool update, char hflag, float dist);
/* `editmesh_undo.cc` */
/** Export for ED_undo_sys. */
void ED_mesh_undosys_type(UndoType *ut);
/* `editmesh_select.cc` */
void EDBM_select_mirrored(
BMEditMesh *em, const Mesh *mesh, int axis, bool extend, int *r_totmirr, int *r_totfail);
#if 0 /* Unused but seems useful to keep. */
/**
* Select mirrored elements on all enabled axis.
* Does nothing if selection symmetry isn't enabled.
*
* \return true if the selection changed.
*/
bool EDBM_select_mirrored_extend_all(Object *obedit, BMEditMesh *em);
#endif
/**
* Nearest vertex under the cursor.
*
* \param dist_px_manhattan_p: (in/out), minimal distance to the nearest and at the end,
* actual distance.
* \param use_select_bias:
* - When true, selected vertices are given a 5 pixel bias
* to make them further than unselected vertices.
* - When false, unselected vertices are given the bias.
* \param use_cycle: Cycle over elements within #FIND_NEAR_CYCLE_THRESHOLD_MIN in order of index.
*/
BMVert *EDBM_vert_find_nearest_ex(ViewContext *vc,
float *dist_px_manhattan_p,
bool use_select_bias,
bool use_cycle,
Span<Base *> bases,
uint *r_base_index);
BMVert *EDBM_vert_find_nearest(ViewContext *vc, float *dist_px_manhattan_p);
BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc,
float *dist_px_manhattan,
float *r_dist_center,
bool use_select_bias,
bool use_cycle,
BMEdge **r_eed_zbuf,
Span<Base *> bases,
uint *r_base_index);
BMEdge *EDBM_edge_find_nearest(ViewContext *vc, float *dist_px_manhattan_p);
/**
* \param use_zbuf_single_px: Special case, when using the back-buffer selection,
* only use the pixel at `vc->mval` instead of using `dist_px_manhattan_p` to search over a larger
* region. This is needed because historically selection worked this way for a long time, however
* it's reasonable that some callers might want to expand the region too. So add an argument to do
* this,
*/
BMFace *EDBM_face_find_nearest_ex(ViewContext *vc,
float *dist_px_manhattan,
float *r_dist_center,
bool use_zbuf_single_px,
bool use_select_bias,
bool use_cycle,
BMFace **r_efa_zbuf,
Span<Base *> bases,
uint *r_base_index);
BMFace *EDBM_face_find_nearest(ViewContext *vc, float *dist_px_manhattan_p);
bool EDBM_unified_findnearest(ViewContext *vc,
Span<Base *> bases,
int *r_base_index,
BMVert **r_eve,
BMEdge **r_eed,
BMFace **r_efa);
bool EDBM_unified_findnearest_from_raycast(ViewContext *vc,
Span<Base *> bases,
bool use_boundary_vertices,
bool use_boundary_edges,
int *r_base_index_vert,
int *r_base_index_edge,
int *r_base_index_face,
BMVert **r_eve,
BMEdge **r_eed,
BMFace **r_efa);
bool EDBM_select_pick(bContext *C, const int mval[2], const SelectPick_Params &params);
/**
* When switching select mode, makes sure selection is consistent for editing
* also for paranoia checks to make sure edge or face mode works.
*/
void EDBM_selectmode_set(BMEditMesh *em, short selectmode);
/**
* Expand & Contract the Selection
* (used when changing modes and Ctrl key held)
*
* Flush the selection up:
* - vert -> edge
* - vert -> face
* - edge -> face
*
* Flush the selection down:
* - face -> edge
* - face -> vert
* - edge -> vert
*/
void EDBM_selectmode_convert(BMEditMesh *em, short selectmode_old, short selectmode_new);
/**
* Select-mode setting utility.
* This operates on tool-settings and all objects passed in.
*/
bool EDBM_selectmode_set_multi_ex(Scene *scene, Span<Object *> objects, const short selectmode);
/**
* High level select-mode setting utility.
* This operates on tool-settings and all edit-mode objects.
*/
bool EDBM_selectmode_set_multi(bContext *C, short selectmode);
/**
* User facing function, handles notification.
*
* \param selectmode_toggle: The mode to adjust based on `action`, must not contain mixed flags.
*/
bool EDBM_selectmode_toggle_multi(
bContext *C, short selectmode_toggle, int action, bool use_extend, bool use_expand);
/**
* Use to disable a select-mode if its enabled, Using another mode as a fallback
* if the disabled mode is the only mode set.
*
* \return true if the mode is changed.
*/
bool EDBM_selectmode_disable(Scene *scene,
BMEditMesh *em,
short selectmode_disable,
short selectmode_fallback);
bool EDBM_deselect_by_material(BMEditMesh *em, short index, bool select);
void EDBM_select_toggle_all(BMEditMesh *em);
void EDBM_select_swap(BMEditMesh *em); /* exported for UV */
bool EDBM_select_interior_faces(BMEditMesh *em);
ViewContext em_setup_viewcontext(bContext *C); /* rename? */
bool EDBM_mesh_deselect_all_multi_ex(Span<Base *> bases);
bool EDBM_mesh_deselect_all_multi(bContext *C);
bool EDBM_selectmode_disable_multi_ex(Scene *scene,
Span<Base *> bases,
short selectmode_disable,
short selectmode_fallback);
bool EDBM_selectmode_disable_multi(bContext *C,
short selectmode_disable,
short selectmode_fallback);
/* `editmesh_preselect_edgering.cc` */
struct EditMesh_PreSelEdgeRing;
EditMesh_PreSelEdgeRing *EDBM_preselect_edgering_create();
void EDBM_preselect_edgering_destroy(EditMesh_PreSelEdgeRing *psel);
void EDBM_preselect_edgering_clear(EditMesh_PreSelEdgeRing *psel);
void EDBM_preselect_edgering_draw(EditMesh_PreSelEdgeRing *psel, const float matrix[4][4]);
void EDBM_preselect_edgering_update_from_edge(EditMesh_PreSelEdgeRing *psel,
BMesh *bm,
BMEdge *eed_start,
int previewlines,
Span<float3> vert_positions);
/* `editmesh_preselect_elem.cc` */
struct EditMesh_PreSelElem;
enum eEditMesh_PreSelPreviewAction {
PRESELECT_ACTION_TRANSFORM = 1,
PRESELECT_ACTION_CREATE = 2,
PRESELECT_ACTION_DELETE = 3,
};
EditMesh_PreSelElem *EDBM_preselect_elem_create();
void EDBM_preselect_elem_destroy(EditMesh_PreSelElem *psel);
void EDBM_preselect_elem_clear(EditMesh_PreSelElem *psel);
void EDBM_preselect_preview_clear(EditMesh_PreSelElem *psel);
void EDBM_preselect_elem_draw(EditMesh_PreSelElem *psel, const float matrix[4][4]);
void EDBM_preselect_elem_update_from_single(EditMesh_PreSelElem *psel,
BMesh *bm,
BMElem *ele,
Span<float3> vert_positions);
void EDBM_preselect_elem_update_preview(
EditMesh_PreSelElem *psel, ViewContext *vc, BMesh *bm, BMElem *ele, const int mval[2]);
void EDBM_preselect_action_set(EditMesh_PreSelElem *psel, eEditMesh_PreSelPreviewAction action);
eEditMesh_PreSelPreviewAction EDBM_preselect_action_get(EditMesh_PreSelElem *psel);
/**
* Extrudes individual edges.
*/
bool EDBM_extrude_edges_indiv(BMEditMesh *em, wmOperator *op, char hflag, bool use_normal_flip);
bool EDBM_smooth_vert(BMEditMesh *em, wmOperator *op);
/* `mesh_ops.cc` */
void ED_operatortypes_mesh();
void ED_operatormacros_mesh();
/**
* Note mesh keymap also for other space?
*/
void ED_keymap_mesh(wmKeyConfig *keyconf);
/* `editface.cc` */
/**
* Copy the face flags, most importantly selection from the mesh to the final evaluated mesh,
* use in object mode when selecting faces (while painting).
*/
void paintface_flush_flags(bContext *C, Object *ob, bool flush_selection, bool flush_hidden);
/**
* \return True when pick finds an element or the selection changed.
*/
bool paintface_mouse_select(bContext *C,
const int mval[2],
const SelectPick_Params &params,
Object *ob);
bool paintface_deselect_all_visible(bContext *C, Object *ob, int action, bool flush_flags);
void paintface_select_linked(bContext *C, Object *ob, const int mval[2], bool select);
void paintface_select_loop(bContext *C, Object *ob, const int mval[2], bool select);
/**
* Grow the selection of faces.
* \param face_step: If true will also select faces that only touch on the corner.
*/
void paintface_select_more(Mesh *mesh, bool face_step);
void paintface_select_less(Mesh *mesh, bool face_step);
bool paintface_minmax(Object *ob, float r_min[3], float r_max[3]);
void paintface_hide(bContext *C, Object *ob, bool unselected);
void paintface_reveal(bContext *C, Object *ob, bool select);
/**
* \note if the caller passes false to flush_flags,
* then they will need to run #paintvert_flush_flags(ob) themselves.
*/
bool paintvert_deselect_all_visible(Object *ob, int action, bool flush_flags);
void paintvert_select_ungrouped(Object *ob, bool extend, bool flush_flags);
/**
* (similar to void `paintface_flush_flags(Object *ob)`)
* copy the vertex flags, most importantly selection from the mesh to the final evaluated mesh,
* use in object mode when selecting vertices (while painting).
*/
void paintvert_flush_flags(Object *ob);
void paintvert_tag_select_update(bContext *C, Object *ob);
void paintvert_select_loop(bContext *C, Object *ob, const int mval[2], const bool select);
/* Select vertices that are connected to already selected vertices. */
void paintvert_select_linked(bContext *C, Object *ob);
/* Select vertices that are linked to the vertex under the given region space coordinates. */
void paintvert_select_linked_pick(bContext *C,
Object *ob,
const int region_coordinates[2],
bool select);
void paintvert_select_more(Mesh *mesh, bool face_step);
void paintvert_select_less(Mesh *mesh, bool face_step);
void paintvert_hide(bContext *C, Object *ob, bool unselected);
void paintvert_reveal(bContext *C, Object *ob, bool select);
/* mirrtopo */
struct MirrTopoStore_t {
intptr_t *index_lookup;
int prev_vert_tot;
int prev_edge_tot;
bool prev_is_editmode;
};
bool ED_mesh_mirrtopo_recalc_check(BMEditMesh *em, Mesh *mesh, MirrTopoStore_t *mesh_topo_store);
void ED_mesh_mirrtopo_init(BMEditMesh *em,
Mesh *mesh,
MirrTopoStore_t *mesh_topo_store,
bool skip_em_vert_array_init);
void ED_mesh_mirrtopo_free(MirrTopoStore_t *mesh_topo_store);
/* `mesh_data.cc` */
void ED_mesh_verts_add(Mesh *mesh, ReportList *reports, int count);
void ED_mesh_edges_add(Mesh *mesh, ReportList *reports, int count);
void ED_mesh_loops_add(Mesh *mesh, ReportList *reports, int count);
void ED_mesh_faces_add(Mesh *mesh, ReportList *reports, int count);
void ED_mesh_verts_remove(Mesh *mesh, ReportList *reports, int count);
void ED_mesh_edges_remove(Mesh *mesh, ReportList *reports, int count);
void ED_mesh_loops_remove(Mesh *mesh, ReportList *reports, int count);
void ED_mesh_faces_remove(Mesh *mesh, ReportList *reports, int count);
void ED_mesh_geometry_clear(Mesh *mesh);
bke::AttributeWriter<bool> ED_mesh_uv_map_pin_layer_ensure(Mesh *mesh, int uv_index);
VArray<bool> ED_mesh_uv_map_pin_layer_get(const Mesh *mesh, int uv_index);
void ED_mesh_uv_ensure(Mesh *mesh, const char *name);
int ED_mesh_uv_add(
Mesh *mesh, const char *name, bool active_set, bool do_init, ReportList *reports);
void ED_mesh_uv_loop_reset(bContext *C, Mesh *mesh);
bool ED_mesh_color_ensure(Mesh *mesh, const char *name);
std::string ED_mesh_color_add(
Mesh *mesh, const char *name, bool active_set, bool do_init, ReportList *reports);
void ED_mesh_report_mirror(ReportList &reports, int totmirr, int totfail);
void ED_mesh_report_mirror_ex(ReportList &reports, int totmirr, int totfail, char selectmode);
KeyBlock *ED_mesh_get_edit_shape_key(const Mesh *me);
/**
* Returns the pinned mesh, the mesh from the pinned object, or the mesh from the active object.
*/
Mesh *ED_mesh_context(bContext *C);
/**
* Split all edges that would appear sharp based on face and edge sharpness tags and the
* auto smooth angle.
*/
void ED_mesh_split_faces(Mesh *mesh);
/* mesh backup */
struct BMBackup {
BMesh *bmcopy;
};
/**
* Save a copy of the #BMesh for restoring later.
*/
BMBackup EDBM_redo_state_store(BMEditMesh *em);
/**
* Restore a BMesh from backup.
*/
void EDBM_redo_state_restore(BMBackup *backup, BMEditMesh *em, bool recalc_looptris)
ATTR_NONNULL(1, 2);
/**
* Delete the backup, flushing it to an edit-mesh.
*/
void EDBM_redo_state_restore_and_free(BMBackup *backup, BMEditMesh *em, bool recalc_looptris)
ATTR_NONNULL(1, 2);
void EDBM_redo_state_free(BMBackup *backup) ATTR_NONNULL(1);
namespace ed::mesh {
wmOperatorStatus join_objects_exec(bContext *C, wmOperator *op);
}
/* `meshtools.cc` */
wmOperatorStatus ED_mesh_shapes_join_objects_exec(bContext *C,
bool ensure_keys_exist,
bool mirror,
ReportList *reports);
/* Mirror lookup API. */
/* Spatial Mirror */
void ED_mesh_mirror_spatial_table_begin(Object *ob, BMEditMesh *em, Mesh *mesh_eval);
void ED_mesh_mirror_spatial_table_end(Object *ob);
int ED_mesh_mirror_spatial_table_lookup(Object *ob,
BMEditMesh *em,
Mesh *mesh_eval,
const float co[3]);
/* Topology Mirror */
/**
* Mode is 's' start, or 'e' end, or 'u' use if end, ob can be NULL.
* \note This is supposed return -1 on error,
* which callers are currently checking for, but is not used so far.
*/
void ED_mesh_mirror_topo_table_begin(Object *ob, Mesh *mesh_eval);
void ED_mesh_mirror_topo_table_end(Object *ob);
/**
* Retrieves mirrored cache vert, or NULL if there isn't one.
* \note calling this without ensuring the mirror cache state is bad.
*/
int mesh_get_x_mirror_vert(Object *ob, Mesh *mesh_eval, int index, bool use_topology);
BMVert *editbmesh_get_x_mirror_vert(
Object *ob, BMEditMesh *em, BMVert *eve, const float co[3], int index, bool use_topology);
/**
* This is a Mesh-based copy of #mesh_get_x_mirror_faces().
*/
int *mesh_get_x_mirror_faces(Object *ob, BMEditMesh *em, Mesh *mesh_eval);
/**
* Wrapper for object-mode/edit-mode.
*
* call #BM_mesh_elem_table_ensure first for edit-mesh.
*/
int ED_mesh_mirror_get_vert(Object *ob, int index);
bool ED_mesh_pick_vert(
bContext *C, Object *ob, const int mval[2], uint dist_px, bool use_zbuf, uint *r_index);
/**
* Face selection in object mode,
* currently only weight-paint and vertex-paint use this.
*
* \return boolean true == Found
*/
bool ED_mesh_pick_face(bContext *C, Object *ob, const int mval[2], uint dist_px, uint *r_index);
/**
* Use when the back buffer stores face index values. but we want a vert.
* This gets the face then finds the closest vertex to mval.
*/
bool ED_mesh_pick_face_vert(
bContext *C, Object *ob, const int mval[2], uint dist_px, uint *r_index);
/**
* Used for paint face loop selection which needs to get closest edge even though in face select
* mode. Changes the select_buffer context to edge selection for this.
*/
bool ED_mesh_pick_edge(bContext *C, Object *ob, const int mval[2], uint dist_px, uint *r_index);
MDeformVert *ED_mesh_active_dvert_get_em(Object *ob, BMVert **r_eve);
MDeformVert *ED_mesh_active_dvert_get_ob(Object *ob, int *r_index);
MDeformVert *ED_mesh_active_dvert_get_only(Object *ob);
void EDBM_mesh_stats_multi(Span<Object *> objects, int totelem[3], int totelem_sel[3]);
void EDBM_mesh_elem_index_ensure_multi(Span<Object *> objects, char htype);
#define ED_MESH_PICK_DEFAULT_VERT_DIST 25
#define ED_MESH_PICK_DEFAULT_FACE_DIST 1
#define USE_LOOPSLIDE_HACK
} // namespace blender

View File

@@ -0,0 +1,173 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#include <optional>
#include "BLI_bounds.hh"
#include "BLI_compute_context.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_string_ref.hh"
#include "BLI_vector_set.hh"
#include "BKE_compute_context_cache_fwd.hh"
#include "NOD_geometry_nodes_closure_location.hh"
#include "NOD_nested_node_id.hh"
#include "ED_node_c.hh"
#include "UI_interface_layout.hh"
namespace blender {
struct SpaceNode;
struct ARegion;
struct Main;
struct bContext;
struct bNodeSocket;
struct bNodeTree;
struct bNodeTreeInterfacePanel;
struct bNodeTreeInterfaceSocket;
struct Object;
struct rcti;
struct rctf;
struct NodesModifierData;
namespace bke {
class bNodeTreeZone;
}
namespace ui {
struct Layout;
} // namespace ui
namespace nodes {
class ItemDeclaration;
}
namespace ed::space_node {
void tree_update(const bContext *C);
float grid_size_get();
/* Compute the nearest 1D coordinate corresponding to the nearest grid in node editors. */
float nearest_node_grid_coord(float co);
/** Update the active node tree based on the context. */
void snode_set_context(const bContext &C);
VectorSet<bNode *> get_selected_nodes(bNodeTree &node_tree);
/**
* \param is_new_node: If the node was just inserted, it is allowed to be inserted in a link, even
* if it is linked already (after link-drag-search).
*/
void node_insert_on_link_flags_set(SpaceNode &snode,
const ARegion &region,
bool attach_enabled,
bool is_new_node);
/**
* Tag the editor to highlight the frame that currently transformed nodes will be attached to.
*/
void node_insert_on_frame_flag_set(SpaceNode &snode, ARegion &region, const int2 &cursor);
void node_insert_on_frame_flag_clear(SpaceNode &snode);
/**
* Assumes link with #NODE_LINK_INSERT_TARGET set.
*/
void node_insert_on_link_flags(Main &bmain, SpaceNode &snode, bool is_new_node);
void node_insert_on_link_flags_clear(bNodeTree &node_tree);
/**
* Draw a single node socket at default size.
*/
void node_socket_draw(bNodeSocket *sock, const rcti *rect, const float color[4], float scale);
void node_draw_nodesocket(const rctf *rect,
const float color_inner[4],
const float color_outline[4],
float outline_thickness,
int shape,
float aspect);
void std_node_socket_colors_get(int socket_type, float *r_color);
/**
* Find the nested node id of a currently visible node in the root tree.
*/
std::optional<nodes::FoundNestedNodeID> find_nested_node_id_in_root(const SpaceNode &snode,
const bNode &node);
std::optional<nodes::FoundNestedNodeID> find_nested_node_id_in_root(
const bNodeTree &root_tree, const ComputeContext *compute_context, const int node_id);
struct ObjectAndModifier {
const Object *object = nullptr;
const NodesModifierData *nmd = nullptr;
};
/**
* Finds the context-modifier for the node editor.
*/
std::optional<ObjectAndModifier> get_modifier_for_node_editor(const SpaceNode &snode);
bool node_editor_is_for_geometry_nodes_modifier(const SpaceNode &snode,
const Object &object,
const NodesModifierData &nmd);
/**
* Get the compute context for the active context that the user is currently looking at in that
* node tree.
*/
[[nodiscard]] const ComputeContext *compute_context_for_edittree(
const SpaceNode &snode, bke::ComputeContextCache &compute_context_cache);
/**
* Get the active compute context for the given socket in the current edittree.
*/
[[nodiscard]] const ComputeContext *compute_context_for_edittree_socket(
const SpaceNode &snode,
bke::ComputeContextCache &compute_context_cache,
const bNodeSocket &socket);
[[nodiscard]] const ComputeContext *compute_context_for_edittree_node(
const SpaceNode &snode, bke::ComputeContextCache &compute_context_cache, const bNode &node);
/**
* Creates a compute context for the given zone. It takes e.g. the current inspection index into
* account.
*/
[[nodiscard]] const ComputeContext *compute_context_for_zone(
const bke::bNodeTreeZone &zone,
bke::ComputeContextCache &compute_context_cache,
const ComputeContext *parent_compute_context);
[[nodiscard]] const ComputeContext *compute_context_for_zones(
const Span<const bke::bNodeTreeZone *> zones,
bke::ComputeContextCache &compute_context_cache,
const ComputeContext *parent_compute_context);
void ui_template_node_asset_menu_items(ui::Layout &layout,
const bContext &C,
StringRef catalog_path,
const ui::NodeAssetMenuOperatorType operator_type);
/** See #ed::space_node::SpaceNode_Runtime::node_can_sync_states. */
Map<int, bool> &node_can_sync_cache_get(SpaceNode &snode);
void node_tree_interface_draw(bContext &C, ui::Layout &layout, bNodeTree &tree);
const char *node_socket_get_label(const bNodeSocket *socket, const char *panel_label = nullptr);
const char *node_socket_get_description(const bNodeSocket *socket);
std::optional<Bounds<float2>> node_bounds(Span<const bNode *> nodes);
std::optional<Bounds<float2>> node_location_bounds(Span<const bNode *> nodes);
/** Find the top-most parent shared by all the nodes, or null if no parent contains all nodes. */
bNode *find_common_parent_node(Span<bNode *> nodes);
} // namespace ed::space_node
} // namespace blender

View File

@@ -0,0 +1,112 @@
/* SPDX-FileCopyrightText: 2009 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
namespace blender {
struct ARegion;
struct ID;
struct Main;
struct Scene;
struct SpaceNode;
struct wmWindow;
struct Tex;
struct View2D;
struct ViewLayer;
struct bContext;
struct bNode;
struct bNodeTree;
namespace bke {
struct bNodeTreeType;
struct bNodeType;
struct bNodeSocketType;
} // namespace bke
#define NODE_GRID_UNIT 20.0f
#define NODE_GRID_STEP_SIZE (NODE_GRID_UNIT * UI_SCALE_FAC) /* Size of node snap grid. */
#define NODE_EDGE_PAN_INSIDE_PAD 2
#define NODE_EDGE_PAN_OUTSIDE_PAD 0 /* Disable clamping for node panning, use whole screen. */
#define NODE_EDGE_PAN_SPEED_RAMP 1
#define NODE_EDGE_PAN_MAX_SPEED 26 /* In UI units per second, slower than default. */
#define NODE_EDGE_PAN_DELAY 0.5f
#define NODE_EDGE_PAN_ZOOM_INFLUENCE 0.5f
/* `space_node.cc` */
void ED_node_cursor_location_get(const SpaceNode *snode, float value[2]);
void ED_node_cursor_location_set(SpaceNode *snode, const float value[2]);
int ED_node_tree_path_length(SpaceNode *snode);
/**
* \param value: The path output at least the size of `ED_node_tree_path_length(snode) + 1`.
*/
void ED_node_tree_path_get(SpaceNode *snode, char *value);
void ED_node_tree_start(ARegion *region, SpaceNode *snode, bNodeTree *ntree, ID *id, ID *from);
void ED_node_tree_push(ARegion *region, SpaceNode *snode, bNodeTree *ntree, bNode *gnode);
void ED_node_tree_pop(ARegion *region, SpaceNode *snode);
int ED_node_tree_depth(SpaceNode *snode);
bNodeTree *ED_node_tree_get(SpaceNode *snode, int level);
void ED_node_set_active_viewer_key(SpaceNode *snode);
/* `drawnode.cc` */
void ED_node_init_butfuncs();
void ED_init_custom_node_type(bke::bNodeType *ntype);
void ED_init_custom_node_socket_type(bke::bNodeSocketType *stype);
void ED_init_standard_node_socket_type(bke::bNodeSocketType *stype);
void ED_init_node_socket_type_virtual(bke::bNodeSocketType *stype);
void ED_node_sample_set(const float col[4]);
void ED_node_type_draw_color(const char *idname, float *r_color);
/* `node_edit.cc` */
void ED_node_set_tree_type(SpaceNode *snode, bke::bNodeTreeType *typeinfo);
bool ED_node_is_compositor(const SpaceNode *snode);
bool ED_node_is_shader(SpaceNode *snode);
bool ED_node_is_texture(SpaceNode *snode);
bool ED_node_is_geometry(const SpaceNode *snode);
bool ED_node_supports_preview(SpaceNode *snode);
/**
* Assumes nothing being done in ntree yet, sets the default in/out node.
* Called from shading buttons or header.
*/
void ED_node_texture_default(const bContext *C, Tex *tex);
void ED_node_post_apply_transform(bContext *C, bNodeTree *ntree);
void ED_node_set_active(
Main *bmain, SpaceNode *snode, bNodeTree *ntree, bNode *node, bool *r_active_texture_changed);
/* `node_compositor_job.cc` */
/**
* Launch a compositor job for the given scene and view layer.
*/
void ED_node_compositor_job(Main *bmain, Scene *scene, ViewLayer *view_layer);
/* `node_ops.cc` */
void ED_operatormacros_node();
/* `node_view.cc` */
/**
* Returns mouse position in image space.
*/
bool ED_space_node_get_position(
Main *bmain, SpaceNode *snode, ARegion *region, const int mval[2], float fpos[2]);
/**
* Returns color in linear space, matching #ED_space_image_color_sample().
* And here we've got recursion in the comments tips...
*/
bool ED_space_node_color_sample(
Main *bmain, SpaceNode *snode, ARegion *region, const int mval[2], float r_col[3]);
} // namespace blender

View File

@@ -0,0 +1,66 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#include "BLI_map.hh"
#include "RE_pipeline.h"
#include "IMB_imbuf.hh"
#include "DNA_material_types.h"
namespace blender {
struct ImBuf;
struct SpaceNode;
struct bContext;
struct bNode;
struct bNodeTree;
struct wmWindowManager;
struct Render;
namespace ed::space_node {
struct NestedTreePreviews {
Render *previews_render = nullptr;
/** Use this map to keep track of the latest #ImBuf used (after freeing the render-result). */
Map<int32_t, ImBuf *> previews_map;
int preview_size;
bool rendering = false;
bool restart_needed = false;
ePreviewType cached_preview_type = MA_FLAT;
ePreviewType rendering_preview_type = MA_FLAT;
uint32_t cached_previews_refresh_state = -1;
uint32_t rendering_previews_refresh_state = -1;
NestedTreePreviews(const int size) : preview_size(size) {}
~NestedTreePreviews()
{
if (this->previews_render) {
RE_FreeRender(this->previews_render);
}
for (ImBuf *ibuf : this->previews_map.values()) {
IMB_freeImBuf(ibuf);
}
}
};
void free_previews(wmWindowManager &wm, SpaceNode &snode);
/**
* \note #node_release_preview_ibuf should be called after this.
*/
ImBuf *node_preview_acquire_ibuf(bNodeTree &ntree,
NestedTreePreviews &tree_previews,
const bNode &node);
void node_release_preview_ibuf(NestedTreePreviews &tree_previews);
/**
* This function returns the `NestedTreePreviews *` for the node-tree shown in the #SpaceNode.
* This is the first function in charge of the previews by calling `ensure_nodetree_previews`.
*/
NestedTreePreviews *get_nested_previews(const bContext &C, SpaceNode &snode);
} // namespace ed::space_node
} // namespace blender

View File

@@ -0,0 +1,124 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
namespace blender {
/** Check if a double value is finite and exactly represents an integer. */
bool ED_numinput_double_is_int(double value);
#define NUM_STR_REP_LEN 64
#define NUM_MAX_ELEMENTS 3
struct bContext;
struct wmEvent;
struct UnitSettings;
struct NumInput {
/** idx_max < NUM_MAX_ELEMENTS */
short idx_max;
int unit_sys;
/** Each value can have a different type */
int unit_type[NUM_MAX_ELEMENTS];
bool unit_use_radians;
/** Flags affecting all values' behavior */
short flag;
/** Per-value flags */
short val_flag[NUM_MAX_ELEMENTS];
/** Direct value of the input */
float val[NUM_MAX_ELEMENTS];
/** Evaluated value before unit scaling (e.g. degrees, not radians). */
double val_no_units[NUM_MAX_ELEMENTS];
/** Original value of the input, for reset */
float val_org[NUM_MAX_ELEMENTS];
/** Increment steps */
float val_inc[NUM_MAX_ELEMENTS];
/** Active element/value */
short idx;
/** String as typed by user for edited value (we assume ASCII world!) */
char str[NUM_STR_REP_LEN];
/** Current position of cursor in edited value str
* (first byte of "current" letter, so 0 for an empty str) */
int str_cur;
};
/** #NumInput.flag */
enum {
NUM_AFFECT_ALL = (1 << 0),
/* (1 << 9) and above are reserved for internal flags! */
};
/** #NumInput::val_flag */
enum {
/* Public! */
NUM_NULL_ONE = (1 << 0),
NUM_NO_NEGATIVE = (1 << 1),
NUM_NO_ZERO = (1 << 2),
NUM_NO_FRACTION = (1 << 3),
/**
* The input string (pre-unit-scale) evaluates to an integer value.
* Used for exact quadrant rotation detection, see `transform_mode_rotate_quadrants.cc`.
*/
NUM_INT_INPUT_VALUE = (1 << 4),
/* (1 << 9) and above are reserved for internal flags! */
};
/* -------------------------------------------------------------------- */
/** \name NumInput
* \{ */
/**
* There are important things to note here for code using numeric-input:
* - Values passed to #applyNumInput() should be valid and are stored as default ones (val_org),
* if it is not EDITED.
* - `bool` returned by #applyNumInput should be used to decide whether to apply
* numeric-input-specific post-process to data.
* - Once #applyNumInput has been called,
* #hasNumInput returns a valid value to decide whether to use numinput as `drawstr`
* source or not (i.e. to call #outputNumInput).
*
* Those two steps have to be separated
* (so do not use a common call to #hasNumInput() to do both in the same time!).
*/
void initNumInput(NumInput *n);
/**
* \param str: Must be NUM_STR_REP_LEN * (idx_max + 1) length.
*/
void outputNumInput(NumInput *n, char *str, const UnitSettings &unit_settings);
bool hasNumInput(const NumInput *n);
/**
* \warning \a vec must be set beforehand otherwise we risk uninitialized vars.
*/
bool applyNumInput(NumInput *n, float *vec);
bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event);
/** Share with `TFM_MODAL_CANCEL` in `transform.h`. */
#define NUM_MODAL_INCREMENT_UP 18
#define NUM_MODAL_INCREMENT_DOWN 19
/**
* \param r_value_no_units: Output for the evaluated value before unit scaling is applied
* (may be null). Useful when the caller needs the original input value for exact comparisons,
* e.g. detecting exact 90-degree multiples before radian conversion introduces imprecision.
*/
bool user_string_to_number(bContext *C,
const char *str,
const UnitSettings &unit,
int type,
double *r_value,
double *r_value_no_units,
bool use_single_line_error,
char **r_error);
/** \} */
} // namespace blender

View File

@@ -0,0 +1,634 @@
/* SPDX-FileCopyrightText: 2008 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
#include <string>
#include "BLI_compiler_attrs.h"
#include "BLI_function_ref.hh"
#include "BLI_map.hh"
#include "BLI_math_matrix_types.hh"
#include "BLI_string_ref.hh"
#include "BLI_vector.hh"
#include "DNA_listBase.h"
#include "DNA_object_enums.h"
#include "DNA_userdef_enums.h"
namespace blender {
struct Base;
struct Depsgraph;
struct EnumPropertyItem;
struct ID;
struct KeyBlock;
struct GpencilModifierData;
struct Main;
struct ModifierData;
struct Object;
struct PointerRNA;
struct ReportList;
struct Scene;
struct ShaderFxData;
struct View3D;
struct ViewLayer;
struct bConstraint;
struct bContext;
struct bPoseChannel;
struct wmKeyConfig;
struct wmOperator;
struct wmOperatorType;
enum eReportType : uint16_t;
enum eAnimvizCalcRange : uint8_t;
namespace ui {
struct Layout;
} // namespace ui
enum eObject_Partype : short;
namespace ed::object {
struct XFormObjectData;
/* `object_edit.cc` */
/** `context.object` */
Object *context_object(const bContext *C);
/**
* Find the correct active object per context (`context.object` or `context.active_object`)
* \note context can be NULL when called from a enum with #PROP_ENUM_NO_CONTEXT.
*/
Object *context_active_object(const bContext *C);
void collection_hide_menu_draw(const bContext *C, ui::Layout &layout);
/**
* Return an array of objects:
* - When in the property space, return the pinned or active object.
* - When in edit-mode/pose-mode, return an array of objects in the mode.
* - Otherwise return selected objects,
* the callers \a filter_fn needs to check of they are editable
* (assuming they need to be modified).
*/
Vector<Object *> objects_in_mode_or_selected(bContext *C,
bool (*filter_fn)(const Object *ob, void *user_data),
void *filter_user_data);
/**
* Set the active material by index.
*
* \param index: A zero based index. This will be clamped to the valid range.
* \return true if the material index changed.
*/
bool material_active_index_set(Object *ob, int index);
/* `object_shapekey.cc` */
/**
* Checks if the currently active Edit Mode on the object is targeting a locked shape key,
* and produces an error message if so (unless \a reports is null).
* \return true if the shape key was locked.
*/
bool shape_key_report_if_locked(const Object *obedit, ReportList *reports);
/**
* Checks if the active shape key of the object is locked, and produces an error message
* if so (unless \a reports is null).
* \return true if the shape key was locked.
*/
bool shape_key_report_if_active_locked(Object *ob, ReportList *reports);
/**
* Checks if any of the shape keys of the object are locked, and produces an error message if so
* (unless \a reports is null).
* \return true if a shape key was locked.
*/
bool shape_key_report_if_any_locked(Object *ob, ReportList *reports);
/**
* Return whether this shapekey is considered 'selected'.
*
* The active shapekey is always considered 'selected', even though it may not
* have its selection flag set.
*/
bool shape_key_is_selected(const Object &object, const KeyBlock &kb, int keyblock_index);
void shape_key_mirror(Object *ob, KeyBlock *kb, bool use_topology, int &totmirr, int &totfail);
/* `object_utils.cc` */
bool calc_active_center_for_editmode(Object *obedit, bool select_only, float r_center[3]);
bool calc_active_center_for_posemode(Object *ob, bool select_only, float r_center[3]);
bool calc_active_center(Object *ob, bool select_only, float r_center[3]);
/* Object Data Container helper API. */
struct XFormObjectData_Container;
XFormObjectData_Container *data_xform_container_create();
void data_xform_container_destroy(XFormObjectData_Container *xds);
/**
* This may be called multiple times with the same data.
* Each time, the original transformations are re-applied, instead of accumulating the changes.
*/
void data_xform_container_update_all(XFormObjectData_Container *xds,
Main *bmain,
Depsgraph *depsgraph);
void data_xform_container_item_ensure(XFormObjectData_Container *xds, Object *ob);
/** Object Skip-Child Container helper API. */
enum {
/**
* The parent is transformed, this is held in place.
*/
XFORM_OB_SKIP_CHILD_PARENT_IS_XFORM = 1,
/**
* The same as #XFORM_OB_SKIP_CHILD_PARENT_IS_XFORM,
* however this objects parent isn't transformed directly.
*/
XFORM_OB_SKIP_CHILD_PARENT_IS_XFORM_INDIRECT = 3,
/**
* Use the parent invert matrix to apply transformation,
* this is needed, because breaks in the selection chain prevents this from being transformed.
* This is used to add the transform which would have been added
* if there weren't breaks in the parent/child chain.
*/
XFORM_OB_SKIP_CHILD_PARENT_APPLY = 2,
};
struct XFormObjectSkipChild_Container;
XFormObjectSkipChild_Container *xform_skip_child_container_create();
void xform_skip_child_container_item_ensure_from_array(XFormObjectSkipChild_Container *xcs,
const Main &bmain,
const Scene *scene,
ViewLayer *view_layer,
Object **objects,
uint objects_len);
void object_xform_skip_child_container_destroy(XFormObjectSkipChild_Container *xcs);
void object_xform_skip_child_container_update_all(XFormObjectSkipChild_Container *xcs,
Main *bmain,
Depsgraph *depsgraph);
void object_xform_skip_child_container_item_ensure(XFormObjectSkipChild_Container *xcs,
Object *ob,
Object *ob_parent_recurse,
int mode);
void object_xform_array_m4(Object **objects, uint objects_len, const float matrix[4][4]);
/* `object_ops.cc` */
void operatortypes_object();
void operatormacros_object();
void keymap_object(wmKeyConfig *keyconf);
/* `object_relations.cc` */
enum eParentType {
PAR_OBJECT,
PAR_ARMATURE,
PAR_ARMATURE_NAME,
PAR_ARMATURE_ENVELOPE,
PAR_ARMATURE_AUTO,
PAR_BONE,
PAR_BONE_RELATIVE,
PAR_CURVE,
PAR_FOLLOW,
PAR_PATH_CONST,
PAR_LATTICE,
PAR_VERTEX,
PAR_VERTEX_TRI,
};
enum eObjectSelect_Mode {
BA_DESELECT = 0,
BA_SELECT = 1,
BA_INVERT = 2,
};
enum eObClearParentTypes {
CLEAR_PARENT_ALL = 0,
CLEAR_PARENT_KEEP_TRANSFORM,
CLEAR_PARENT_INVERSE,
};
#ifdef __RNA_TYPES_H__
/** Operator Property: `OBJECT_OT_parent_clear`. */
extern const EnumPropertyItem prop_clear_parent_types[];
/** Operator Property: `OBJECT_OT_parent_set`. */
extern const EnumPropertyItem prop_make_parent_types[];
#endif
/**
* Set the object's parent, return true if successful.
*/
bool parent_set(ReportList *reports,
const bContext *C,
Scene *scene,
Object *const ob,
Object *const par,
int partype,
bool xmirror,
bool keep_transform,
const int vert_par[3]);
void parent_clear(Object *ob, int type);
/**
* Simple API for object selection, rather than just using the flag
* this takes into account the 'restrict selection in 3d view' flag.
* deselect works always, the restriction just prevents selection
*
* \note Caller must send a `NC_SCENE | ND_OB_SELECT` notifier
* (or a `NC_SCENE | ND_OB_VISIBLE` in case of visibility toggling).
*/
void base_select(Base *base, eObjectSelect_Mode mode);
/**
* Change active base, it includes the notifier
*/
void base_activate(bContext *C, Base *base);
void base_activate_with_mode_exit_if_needed(bContext *C, Base *base);
/**
* Call when the active base has changed.
*/
void base_active_refresh(Main *bmain, Scene *scene, ViewLayer *view_layer);
/**
* Remove base from a specific scene.
* \note now unlinks constraints as well.
*/
void base_free_and_unlink(Main *bmain, Scene *scene, Object *ob);
/**
* Remove base from a specific scene.
* `ob` must not be indirectly used.
*/
void base_free_and_unlink_no_indirect_check(Main *bmain, Scene *scene, Object *ob);
bool base_deselect_all_ex(const Main &bmain,
const Scene *scene,
ViewLayer *view_layer,
View3D *v3d,
int action,
bool *r_any_visible);
bool base_deselect_all(
const Main &bmain, const Scene *scene, ViewLayer *view_layer, View3D *v3d, int action);
/**
* Single object duplicate, if `dupflag == 0`, fully linked, else it uses the flags given.
* Leaves selection of base/object unaltered.
* \note don't call this within a loop since clear_* functions loop over the entire database.
* \note caller must do `DAG_relations_tag_update(bmain);`
* this is not done automatic since we may duplicate many objects in a batch.
*/
Base *add_duplicate(
Main *bmain, Scene *scene, ViewLayer *view_layer, Base *base, eDupli_ID_Flags dupflag);
void parent_set(Object *ob, Object *parent, eObject_Partype type, const char *substr);
std::string drop_named_material_tooltip(bContext *C, StringRef name, const int mval[2]);
std::string drop_geometry_nodes_tooltip(bContext *C, PointerRNA *properties, const int mval[2]);
/** Bit-flags for enter/exit edit-mode. */
enum {
EM_FREEDATA = (1 << 0),
EM_NO_CONTEXT = (1 << 1),
};
/**
* \param flag:
* - If #EM_FREEDATA isn't in the flag, use #editmode_load directly.
*/
bool editmode_exit_ex(Main *bmain, Scene *scene, Object *obedit, int flag);
bool editmode_exit(bContext *C, int flag);
/**
* Support freeing edit-mode data without flushing it back to the object.
*
* \return true if data was freed.
*/
bool editmode_free_ex(Main *bmain, Object *obedit);
bool editmode_exit_multi_ex(Main *bmain, Scene *scene, ViewLayer *view_layer, int flag);
bool editmode_exit_multi(bContext *C, int flag);
bool editmode_enter_ex(Main *bmain, Scene *scene, Object *ob, int flag);
bool editmode_enter(bContext *C, int flag);
bool editmode_load(Main *bmain, Object *obedit);
void location_from_view(bContext *C, float loc[3]);
void rotation_from_quat(float rot[3], const float quat[4], char align_axis);
void rotation_from_view(bContext *C, float rot[3], char align_axis);
void init_transform_on_add(Object *object, const float loc[3], const float rot[3]);
/**
* Uses context to figure out transform for primitive.
* Returns standard diameter.
*/
float new_primitive_matrix(bContext *C,
Object *obedit,
const float loc[3],
const float rot[3],
const float scale[3],
float primmat[4][4]);
/**
* Avoid allowing too much insane values even by typing (typos can hang/crash Blender otherwise).
*/
#define OBJECT_ADD_SIZE_MAXF 1.0e12f
void add_unit_props_size(wmOperatorType *ot);
void add_unit_props_radius_ex(wmOperatorType *ot, float default_value);
void add_unit_props_radius(wmOperatorType *ot);
void add_generic_props(wmOperatorType *ot, bool do_editmode);
void add_mesh_props(wmOperatorType *ot);
void add_generic_get_opts(bContext *C,
wmOperator *op,
char view_align_axis,
float r_loc[3],
float r_rot[3],
float r_scale[3],
bool *r_enter_editmode,
unsigned short *r_local_view_bits,
bool *r_is_view_aligned);
/**
* For object add primitive operators, or for object creation when `obdata != NULL`.
* \param obdata: Assigned to #Object.data, with increased user count.
*
* \note Do not call undo push in this function (users of this function have to).
*/
Object *add_type_with_obdata(bContext *C,
int type,
const char *name,
const float loc[3],
const float rot[3],
bool enter_editmode,
ushort local_view_bits,
ID *obdata);
Object *add_type(bContext *C,
int type,
const char *name,
const float loc[3],
const float rot[3],
bool enter_editmode,
unsigned short local_view_bits) ATTR_NONNULL(1) ATTR_RETURNS_NONNULL;
/**
* Not an especially efficient function, only added so the single user button can be functional.
*/
void object_single_user_make(Main *bmain, Scene *scene, Object *ob);
void single_obdata_user_make(Main *bmain, Scene *scene, Object *ob);
/* object motion paths */
/**
* Clear motion paths for all objects.
*/
void motion_paths_clear(bContext *C, bool only_selected);
/**
* Recalculate the motion paths on the given objects. This includes bones when recalculating
* armature objects.
*/
void motion_paths_recalc(bContext *C,
Scene *scene,
const eAnimvizCalcRange range,
const Span<Object *> objects);
/**
* Recalculate motion paths on all selected objects. This includes bones when recalculating
* armature objects.
*/
void motion_paths_recalc_selected(bContext *C, Scene *scene, eAnimvizCalcRange range);
/**
* Recalculate motion paths on all visible objects. This includes bones when recalculating armature
* objects.
*/
void motion_paths_recalc_visible(bContext *C, Scene *scene, eAnimvizCalcRange range);
/* constraints */
/**
* If object is in pose-mode, return active bone constraints, else object constraints.
* No constraints are returned for a bone on an inactive bone-layer.
*/
ListBaseT<bConstraint> *constraint_active_list(Object *ob);
/**
* Get the constraints for the active pose bone. Bone may be on an inactive bone-layer
* (unlike #constraint_active_list, such constraints are not excluded here).
*/
ListBaseT<bConstraint> *pose_constraint_list(const bContext *C);
/**
* Find the list that a given constraint belongs to,
* and/or also get the pose-channel this is from (if applicable).
*/
ListBaseT<bConstraint> *constraint_list_from_constraint(Object *ob,
bConstraint *con,
bPoseChannel **r_pchan);
/**
* Single constraint.
*/
bConstraint *constraint_active_get(Object *ob);
void object_test_constraints(Main *bmain, Object *ob);
void constraint_active_set(Object *ob, bConstraint *con);
void constraint_update(Main *bmain, Object *ob);
void constraint_dependency_update(Main *bmain, Object *ob);
void constraint_tag_update(Main *bmain, Object *ob, bConstraint *con);
void constraint_dependency_tag_update(Main *bmain, Object *ob, bConstraint *con);
bool constraint_move_to_index(Object *ob, bConstraint *con, int index);
void constraint_link(Main *bmain,
Object *ob_dst,
ListBaseT<bConstraint> *dst,
ListBaseT<bConstraint> *src);
void constraint_copy_for_object(Main *bmain, Object *ob_dst, bConstraint *con);
void constraint_copy_for_pose(Main *bmain, Object *ob_dst, bPoseChannel *pchan, bConstraint *con);
/* `object_modes.cc` */
/**
* Checks the mode to be set is compatible with the object
* should be made into a generic function
*/
bool mode_compat_test(const Object *ob, eObjectMode mode);
/**
* Set the provided object's mode to one that is compatible with the provided mode.
*
* \returns true if the provided object's mode matches the provided mode, or if the function was
* able to set the object back into Object Mode.
*
* This is so each mode toggle operator exec function can call this function to ensure the current
* mode runtime data is cleaned up prior to entering a new mode.
*/
bool mode_compat_set(bContext *C, Object *ob, eObjectMode mode, ReportList *reports);
bool mode_set_ex(bContext *C, eObjectMode mode, bool use_undo, ReportList *reports);
bool mode_set(bContext *C, eObjectMode mode);
void mode_generic_exit(Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob);
bool mode_generic_has_data(Depsgraph *depsgraph, const Object *ob);
void posemode_set_for_weight_paint(bContext *C, Main *bmain, Object *ob, bool is_mode_set);
/**
* Return the index of an object in a mode (typically edit/pose mode).
*
* Useful for operators with multi-mode editing to be able to redo an action on an object
* by its index which (unlike pointers) the operator can store for redo.
*
* The indices aren't intended to be useful from Python scripts,
* although they are not prevented from passing them in, this is mainly to enable redo.
* For scripts it's more convenient to set the object active before operating on it.
*
* \note The active object is always index 0.
*/
int object_in_mode_to_index(const Main &bmain,
const Scene *scene,
ViewLayer *view_layer,
eObjectMode mode,
const Object *ob);
/**
* Access the object from the index returned by #object_in_mode_to_index.
*/
Object *object_in_mode_from_index(
const Main &bmain, const Scene *scene, ViewLayer *view_layer, eObjectMode mode, int index);
/**
* Retrieve the alpha factors of the currently active mode transfer overlay animations. The key is
* the object ID name to prevent possible storage of stale pointers and because the #session_uid
* isn't available on evaluated objects.
*/
Map<std::string, float, 1> mode_transfer_overlay_current_state();
/* `object_modifier.cc` */
enum {
MODIFIER_APPLY_DATA = 1,
MODIFIER_APPLY_SHAPE,
};
/**
* Add a modifier to given object, including relevant extra processing needed by some physics types
* (particles, simulations...).
*
* \param scene: is only used to set current frame in some cases, and may be NULL.
*/
ModifierData *modifier_add(
ReportList *reports, Main *bmain, Scene *scene, Object *ob, const char *name, int type);
bool modifier_remove(ReportList *reports, Main *bmain, Scene *scene, Object *ob, ModifierData *md);
void modifiers_clear(Main *bmain, Scene *scene, Object *ob);
bool modifier_move_down(ReportList *reports, eReportType error_type, Object *ob, ModifierData *md);
bool modifier_move_up(ReportList *reports, eReportType error_type, Object *ob, ModifierData *md);
bool modifier_move_to_index(ReportList *reports,
eReportType error_type,
Object *ob,
ModifierData *md,
int index,
bool allow_partial);
bool convert_psys_to_mesh(ReportList *reports,
Main *bmain,
Depsgraph *depsgraph,
Scene *scene,
ViewLayer *view_layer,
Object *ob,
ModifierData *md);
bool modifier_apply(Main *bmain,
ReportList *reports,
Depsgraph *depsgraph,
Scene *scene,
Object *ob,
ModifierData *md,
int mode,
bool keep_modifier,
bool do_all_keyframes);
bool modifier_copy(ReportList *reports, Main *bmain, Scene *scene, Object *ob, ModifierData *md);
void modifier_link(bContext *C, Object *ob_dst, Object *ob_src);
ModifierData *modifier_copy_to_object(Main *bmain,
const Scene *scene,
const Object *ob_src,
const ModifierData *md,
Object *ob_dst,
ReportList *reports);
/**
* If the object data of 'orig_ob' has other users, run 'callback' on
* each of them.
*
* If include_orig is true, the callback will run on 'orig_ob' too.
*
* If the callback ever returns true, iteration will stop and the
* function value will be true. Otherwise the function returns false.
*/
bool iter_other(Main *bmain,
Object *orig_ob,
bool include_orig,
bool (*callback)(Object *ob, void *callback_data),
void *callback_data);
/**
* Use with #iter_other(). Sets the total number of levels
* for any multi-res modifiers on the object to the int pointed to by callback_data.
*/
bool multires_update_totlevels(Object *ob, void *totlevel_v);
/* `object_shader_fx.cc` */
ShaderFxData *shaderfx_add(
ReportList *reports, Main *bmain, Scene *scene, Object *ob, const char *name, int type);
bool shaderfx_remove(ReportList *reports, Main *bmain, Object *ob, ShaderFxData *fx);
void shaderfx_clear(Main *bmain, Object *ob);
int shaderfx_move_down(ReportList *reports, Object *ob, ShaderFxData *fx);
int shaderfx_move_up(ReportList *reports, Object *ob, ShaderFxData *fx);
bool shaderfx_move_to_index(ReportList *reports, Object *ob, ShaderFxData *fx, int index);
void shaderfx_link(Object *dst, Object *src);
void shaderfx_copy(Object *dst, ShaderFxData *fx);
/* `object_select.cc` */
void select_linked_by_id(bContext *C, ID *id);
void check_force_modifiers(Main *bmain, Scene *scene, Object *object);
/**
* If id is not already an Object, try to find an object that uses it as data.
* Prefers active, then selected, then visible/selectable.
*/
Base *find_first_by_data_id(const Main &bmain, const Scene *scene, ViewLayer *view_layer, ID *id);
/**
* Select and make the target object active in the view layer.
* If already selected, selection isn't changed.
*
* \returns false if not found in current view layer
*/
bool jump_to_object(bContext *C, Object *ob, bool reveal_hidden);
/**
* Select and make the target object and bone active.
* Switches to Pose mode if in Object mode so the selection is visible.
* Un-hides the target bone and bone layer if necessary.
*
* \returns false if object not in layer, bone not found, or other error
*/
bool jump_to_bone(bContext *C, Object *ob, const char *bone_name, bool reveal_hidden);
/* `object_data_transform.cc` */
struct XFormObjectData {
ID *id;
XFormObjectData() = default;
virtual ~XFormObjectData() = default;
};
std::unique_ptr<XFormObjectData> data_xform_create(ID *id);
std::unique_ptr<XFormObjectData> data_xform_create_from_edit_mode(ID *id);
void data_xform_by_mat4(XFormObjectData &xod, const float4x4 &transform);
void data_xform_restore(XFormObjectData &xod);
void data_xform_tag_update(XFormObjectData &xod);
void ui_template_modifier_asset_menu_items(ui::Layout &layout,
StringRef catalog_path,
bool skip_essentials);
} // namespace ed::object
} // namespace blender

View File

@@ -0,0 +1,109 @@
/* SPDX-FileCopyrightText: 2008 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
#include <optional>
namespace blender {
struct EnumPropertyItem;
struct ID;
struct MDeformVert;
struct Object;
struct PointerRNA;
struct PropertyRNA;
struct SpaceNode;
struct bContext;
struct bDeformGroup;
#define WEIGHT_REPLACE 1
#define WEIGHT_ADD 2
#define WEIGHT_SUBTRACT 3
namespace ed::object {
bool vgroup_sync_from_pose(Object *ob);
void vgroup_select_by_name(Object *ob, const char *name);
/**
* Removes out of range #MDeformWeights
*/
void vgroup_data_clamp_range(ID *id, int total);
/**
* Matching index only.
*/
bool vgroup_array_copy(Object *ob, Object *ob_from);
bool vgroup_parray_alloc(ID *id,
MDeformVert ***dvert_arr,
int *dvert_tot,
bool use_vert_sel,
std::optional<int> current_frame = {});
/**
* For use with tools that use vgroup_parray_alloc with \a use_vert_sel ==
* true. This finds the unselected mirror deform verts and copies the weights to them from the
* selected.
*
* \note \a dvert_array has mirrored weights filled in,
* in case cleanup operations are needed on both.
*/
void vgroup_parray_mirror_sync(Object *ob,
MDeformVert **dvert_array,
int dvert_tot,
const bool *vgroup_validmap,
int vgroup_tot);
/**
* Fill in the pointers for mirror verts (as if all mirror verts were selected too).
*
* similar to #vgroup_parray_mirror_sync but only fill in mirror points.
*/
void vgroup_parray_mirror_assign(Object *ob, MDeformVert **dvert_array, int dvert_tot);
void vgroup_parray_remove_zero(MDeformVert **dvert_array,
int dvert_tot,
const bool *vgroup_validmap,
int vgroup_tot,
float epsilon,
bool keep_single);
void vgroup_parray_to_weight_array(const MDeformVert **dvert_array,
int dvert_tot,
float *dvert_weights,
int def_nr);
void vgroup_parray_from_weight_array(MDeformVert **dvert_array,
int dvert_tot,
const float *dvert_weights,
int def_nr,
bool remove_zero);
void vgroup_mirror(Object *ob,
bool mirror_weights,
bool flip_vgroups,
bool all_vgroups,
bool use_topology,
int *r_totmirr,
int *r_totfail);
/**
* Called while not in editmode.
*/
void vgroup_vert_add(Object *ob, bDeformGroup *dg, int vertnum, float weight, int assignmode);
/**
* Mesh object mode, lattice can be in edit-mode.
*/
void vgroup_vert_remove(Object *ob, bDeformGroup *dg, int vertnum);
float vgroup_vert_weight(Object *ob, bDeformGroup *dg, int vertnum);
/**
* Use when adjusting the active vertex weight and apply to mirror vertices.
*/
void vgroup_vert_active_mirror(Object *ob, int def_nr);
const EnumPropertyItem *vgroup_selection_itemf_helper(const bContext *C,
PointerRNA *ptr,
PropertyRNA *prop,
bool *r_free,
unsigned int selection_mask);
} // namespace ed::object
} // namespace blender

View File

@@ -0,0 +1,68 @@
/* SPDX-FileCopyrightText: 2015 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
#include "DNA_listBase.h"
namespace blender {
struct Base;
struct SpaceOutliner;
struct bContext;
struct ID;
struct Bone;
struct PointerRNA;
bool ED_outliner_collections_editor_poll(bContext *C);
/**
* Populates the `objects` #ListBaseT with all the outliner selected objects
* We store it as `(Object *)LinkData->data`.
*
* \param objects: Expected to be empty.
*/
void ED_outliner_selected_objects_get(const bContext *C, ListBaseT<LinkData> *objects);
/**
* Get base of object under cursor. Used for eyedropper tool.
*/
Base *ED_outliner_give_base_under_cursor(bContext *C, const int mval[2]);
/**
* Get the PointerRNA at the given coordinates. ONLY works for bone structs at the moment. Can be
* extended to work with other structs if the need arises.
*/
bool ED_outliner_give_rna_under_cursor(bContext *C, const int mval[2], PointerRNA *r_ptr);
/**
* Functions for tagging outliner selection syncing is dirty from operators.
*/
void ED_outliner_select_sync_from_object_tag(bContext *C);
void ED_outliner_select_sync_from_edit_bone_tag(bContext *C);
void ED_outliner_select_sync_from_pose_bone_tag(bContext *C);
void ED_outliner_select_sync_from_sequence_tag(const bContext *C);
void ED_outliner_select_sync_from_all_tag(bContext *C);
bool ED_outliner_select_sync_is_dirty(const bContext *C);
/**
* Set clean outliner and mark other outliners for syncing.
*/
void ED_outliner_select_sync_from_outliner(bContext *C, SpaceOutliner *space_outliner);
/**
* Copy sync select dirty flag from window manager to all outliners to be synced lazily on draw.
*/
void ED_outliner_select_sync_flag_outliners(const bContext *C);
int ED_outliner_icon_from_id(const ID &id);
bool ED_outliner_support_searching(const SpaceOutliner *space_outliner);
} // namespace blender

View File

@@ -0,0 +1,164 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
#include "DNA_view3d_enums.h"
#include <cstdint>
namespace blender {
enum class PaintMode : int8_t;
struct bContext;
struct bToolRef;
struct Depsgraph;
struct Image;
struct ImageUndoStep;
struct ImageUser;
struct ImBuf;
struct Main;
struct Object;
struct PaintModeSettings;
struct PaintTileMap;
struct ReportList;
struct Scene;
struct UndoStep;
struct UndoType;
struct wmKeyConfig;
struct wmOperator;
/* `paint_ops.cc` */
void ED_operatortypes_paint();
void ED_operatormacros_paint();
void ED_keymap_paint(wmKeyConfig *keyconf);
/* `paint_image.cc` */
void ED_imapaint_clear_partial_redraw();
void ED_imapaint_dirty_region(
Image *ima, ImBuf *ibuf, ImageUser *iuser, int x, int y, int w, int h, bool find_old);
void ED_imapaint_bucket_fill(bContext *C,
const float color[3],
wmOperator *op,
const int mouse[2]);
/* `paint_image_proj.cc` */
void ED_paint_data_warning(
ReportList *reports, bool has_uvs, bool has_mat, bool has_tex, bool has_stencil);
/**
* Make sure that active object has a material,
* and assign UVs and image layers if they do not exist.
*/
bool ED_paint_proj_mesh_data_check(Scene &scene,
Object &ob,
bool *r_has_uvs,
bool *r_has_mat,
bool *r_has_tex,
bool *r_has_stencil);
/* `image_undo.cc` */
/**
* The caller is responsible for running #ED_image_undo_push_end,
* failure to do so causes an invalid state for the undo system.
*/
void ED_image_undo_push_begin(const char *name, PaintMode paint_mode);
void ED_image_undo_push_begin_with_image(const char *name,
Image *image,
ImBuf *ibuf,
ImageUser *iuser);
void ED_image_undo_push_begin_with_image_all_udims(const char *name,
Image *image,
ImageUser *iuser);
void ED_image_undo_push(Image *image, ImBuf *ibuf, ImageUser *iuser, ImageUndoStep *us);
void ED_image_undo_push_end();
/**
* Restore painting image to previous state. Used for anchored and drag-dot style brushes.
*/
void ED_image_undo_restore(UndoStep *us);
/** Export for ED_undo_sys. */
void ED_image_undosys_type(UndoType *ut);
const ImBuf *ED_image_paint_tile_find(PaintTileMap *paint_tile_map,
Image *image,
ImBuf *ibuf,
ImageUser *iuser,
int x_tile,
int y_tile,
unsigned short **r_mask,
bool validate);
const ImBuf *ED_image_paint_tile_push(PaintTileMap *paint_tile_map,
Image *image,
ImBuf *ibuf,
ImageUser *iuser,
int x_tile,
int y_tile,
unsigned short **r_mask,
bool **r_valid,
bool use_thread_lock,
bool find_prev);
void ED_image_paint_tile_lock_init();
void ED_image_paint_tile_lock_end();
PaintTileMap *ED_image_paint_tile_map_get();
#define ED_IMAGE_UNDO_TILE_BITS 6
#define ED_IMAGE_UNDO_TILE_SIZE (1 << ED_IMAGE_UNDO_TILE_BITS)
#define ED_IMAGE_UNDO_TILE_NUMBER(size) \
(((size) + ED_IMAGE_UNDO_TILE_SIZE - 1) >> ED_IMAGE_UNDO_TILE_BITS)
/* `paint_curve_undo.cc` */
void ED_paintcurve_undo_push_begin(const char *name);
void ED_paintcurve_undo_push_end(bContext *C);
/** Export for ED_undo_sys. */
void ED_paintcurve_undosys_type(UndoType *ut);
/* `paint_canvas.cc` */
/** Color type of an object can be overridden in sculpt/paint mode. */
eV3DShadingColorType ED_paint_shading_color_override(bContext *C,
const PaintModeSettings *settings,
Object &ob,
eV3DShadingColorType orig_color_type);
/**
* Does the given tool use a paint canvas.
*
* When #tref isn't given the active tool from the context is used.
*/
bool ED_paint_brush_type_use_canvas(bContext *C, bToolRef *tref);
/** Store the last used tool in the sculpt session. */
void ED_paint_brush_type_update_sticky_shading_color(bContext *C, Object *ob);
void ED_object_vpaintmode_enter_ex(Main &bmain, Depsgraph &depsgraph, Scene &scene, Object &ob);
void ED_object_vpaintmode_enter(bContext *C, Depsgraph &depsgraph);
void ED_object_wpaintmode_enter_ex(Main &bmain, Depsgraph &depsgraph, Scene &scene, Object &ob);
void ED_object_wpaintmode_enter(bContext *C, Depsgraph &depsgraph);
void ED_object_vpaintmode_exit_ex(Object &ob);
void ED_object_vpaintmode_exit(bContext *C);
void ED_object_wpaintmode_exit_ex(Object &ob);
void ED_object_wpaintmode_exit(bContext *C);
void ED_object_texture_paint_mode_enter_ex(Main &bmain,
Scene &scene,
Depsgraph &depsgraph,
Object &ob);
void ED_object_texture_paint_mode_enter(bContext *C);
void ED_object_texture_paint_mode_exit_ex(Main &bmain, Scene &scene, Object &ob);
void ED_object_texture_paint_mode_exit(bContext *C);
} // namespace blender

View File

@@ -0,0 +1,62 @@
/* SPDX-FileCopyrightText: 2007 by Janne Karhu. All rights reserved.
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
#include "BLI_math_vector_types.hh"
namespace blender {
struct Depsgraph;
struct Object;
struct PTCacheEdit;
struct ParticleEditSettings;
struct ParticleSystem;
struct Scene;
struct SelectPick_Params;
struct UndoType;
struct ViewLayer;
struct bContext;
struct rcti;
struct wmGenericUserData;
/* particle edit mode */
void PE_free_ptcache_edit(PTCacheEdit *edit);
int PE_start_edit(PTCacheEdit *edit);
/* access */
PTCacheEdit *PE_get_current_from_psys(ParticleSystem *psys);
PTCacheEdit *PE_get_current(Depsgraph *depsgraph, Scene *scene, Object *ob);
PTCacheEdit *PE_create_current(Depsgraph *depsgraph, Scene *scene, Object *ob);
void PE_current_changed(Depsgraph *depsgraph, Scene *scene, Object *ob);
int PE_minmax(Depsgraph *depsgraph, Scene *scene, ViewLayer *view_layer, float3 &min, float3 &max);
ParticleEditSettings *PE_settings(Scene *scene);
/* update calls */
void PE_hide_keys_time(Scene *scene, PTCacheEdit *edit, float cfra);
void PE_update_object(Depsgraph *depsgraph, Scene *scene, Object *ob, int useflag);
/* selection tools */
bool PE_mouse_particles(bContext *C, const int mval[2], const SelectPick_Params &params);
bool PE_box_select(bContext *C, const rcti *rect, int sel_op);
bool PE_circle_select(
bContext *C, wmGenericUserData *wm_userdata, int sel_op, const int mval[2], float rad);
int PE_lasso_select(bContext *C, const int mcoords[][2], int mcoords_len, int sel_op);
bool PE_deselect_all_visible_ex(PTCacheEdit *edit);
bool PE_deselect_all_visible(bContext *C);
/* `particle_edit_undo.cc` */
/** Export for ED_undo_sys. */
void ED_particle_undosys_type(UndoType *ut);
} // namespace blender

View File

@@ -0,0 +1,53 @@
/* SPDX-FileCopyrightText: 2007 by Janne Karhu. All rights reserved.
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
namespace blender {
struct bContext;
struct Depsgraph;
struct Main;
struct Object;
struct ReportList;
struct Scene;
struct wmKeyConfig;
enum eRigidBodyCon_Type : short;
enum eRigidBodyOb_Type : short;
/* `particle_edit.cc` */
bool ED_object_particle_edit_mode_supported(const Object *ob);
void ED_object_particle_edit_mode_enter_ex(Depsgraph *depsgraph, Scene *scene, Object *ob);
void ED_object_particle_edit_mode_enter(bContext *C);
void ED_object_particle_edit_mode_exit_ex(Scene *scene, Object *ob);
void ED_object_particle_edit_mode_exit(bContext *C);
bool PE_poll(bContext *C);
bool PE_hair_poll(bContext *C);
bool PE_poll_view3d(bContext *C);
/* `rigidbody_object.cc` */
bool ED_rigidbody_object_add(
Main *bmain, Scene *scene, Object *ob, eRigidBodyOb_Type type, ReportList *reports);
void ED_rigidbody_object_remove(Main *bmain, Scene *scene, Object *ob);
/* `rigidbody_constraint.cc` */
bool ED_rigidbody_constraint_add(
Main *bmain, Scene *scene, Object *ob, eRigidBodyCon_Type type, ReportList *reports);
void ED_rigidbody_constraint_remove(Main *bmain, Scene *scene, Object *ob);
/* operators */
void ED_operatortypes_physics();
void ED_keymap_physics(wmKeyConfig *keyconf);
} // namespace blender

View File

@@ -0,0 +1,154 @@
/* SPDX-FileCopyrightText: 2025 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
#include <limits>
#include <optional>
#include "BLI_index_mask_fwd.hh"
#include "BLI_math_matrix_types.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_vector_set.hh"
#include "DNA_windowmanager_enums.h"
namespace blender {
struct ARegion;
struct bContext;
struct PointCloud;
struct rcti;
struct UndoType;
struct wmKeyConfig;
struct wmOperator;
struct wmOperatorType;
namespace bke {
enum class AttrType : int16_t;
struct GSpanAttributeWriter;
} // namespace bke
class GMutableSpan;
enum eSelectOp : int8_t;
namespace ed::pointcloud {
void operatortypes_pointcloud();
void operatormacros_pointcloud();
void keymap_pointcloud(wmKeyConfig *keyconf);
void undosys_type_register(UndoType *ut);
VectorSet<PointCloud *> get_unique_editable_pointclouds(const bContext &C);
/* -------------------------------------------------------------------- */
/** \name Selection
*
* Selection on point cloud are stored per-point. It
* can be stored with a float or boolean data-type. The boolean data-type is faster, smaller, and
* corresponds better to edit-mode selections, but the float data type is useful for soft selection
* (like masking) in sculpt mode.
*
* The attribute API is used to do the necessary type and domain conversions when necessary, and
* can handle most interaction with the selection attribute, but these functions implement some
* helpful utilities on top of that.
* \{ */
void fill_selection_true(GMutableSpan span);
void fill_selection_false(GMutableSpan selection, const IndexMask &mask);
void fill_selection_true(GMutableSpan selection, const IndexMask &mask);
/**
* Return true if any element is selected, on either domain with either type.
*/
bool has_anything_selected(const PointCloud &pointcloud);
/**
* (De)select all the points.
*
* \param action: One of #SEL_TOGGLE, #SEL_SELECT, #SEL_DESELECT, or #SEL_INVERT.
* See `ED_select_utils.hh`.
*/
void select_all(PointCloud &pointcloud, int action);
/**
* If the selection_id attribute doesn't exist, create it with the requested type (bool or float).
*/
bke::GSpanAttributeWriter ensure_selection_attribute(PointCloud &pointcloud,
bke::AttrType create_type);
bool select_box(PointCloud &pointcloud,
const ARegion &region,
const float4x4 &projection,
const rcti &rect,
const eSelectOp sel_op);
bool select_lasso(PointCloud &pointcloud,
const ARegion &region,
const float4x4 &projection,
const Span<int2> lasso_coords,
const eSelectOp sel_op);
bool select_circle(PointCloud &pointcloud,
const ARegion &region,
const float4x4 &projection,
const int2 coord,
const float radius,
const eSelectOp sel_op);
struct FindClosestData {
int index = -1;
float distance_sq = std::numeric_limits<float>::max();
};
std::optional<FindClosestData> find_closest_point_to_screen_co(
const ARegion &region,
const Span<float3> positions,
const float4x4 &projection,
const IndexMask &points_mask,
const float2 mouse_pos,
const float radius,
const FindClosestData &initial_closest);
IndexMask retrieve_selected_points(const PointCloud &pointcloud, IndexMaskMemory &memory);
/** \} */
/* -------------------------------------------------------------------- */
/** \name Editing
* \{ */
/**
* Remove selected points based on the ".selection" attribute.
* \returns true if any point was removed.
*/
bool remove_selection(PointCloud &pointcloud);
PointCloud *copy_selection(const PointCloud &src, const IndexMask &mask);
/** \} */
/* -------------------------------------------------------------------- */
/** \name Poll Functions
* \{ */
bool editable_pointcloud_in_edit_mode_poll(bContext *C);
/** \} */
/* -------------------------------------------------------------------- */
/** \name Operators
* \{ */
void POINTCLOUD_OT_attribute_set(wmOperatorType *ot);
void POINTCLOUD_OT_duplicate(wmOperatorType *ot);
void POINTCLOUD_OT_separate(wmOperatorType *ot);
wmOperatorStatus join_objects_exec(bContext *C, wmOperator *op);
/** \} */
} // namespace ed::pointcloud
} // namespace blender

View File

@@ -0,0 +1,158 @@
/* SPDX-FileCopyrightText: 2005 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
#include "DNA_ID_enums.h"
#include "DNA_material_types.h"
#include "DNA_vec_types.h"
namespace blender {
struct DEGEditorUpdateContext;
struct Depsgraph;
struct ID;
struct MTex;
struct Main;
struct Render;
struct Scene;
struct ScrArea;
struct bContext;
struct bScreen;
struct PreviewImage;
struct uiPreview;
struct ViewLayer;
struct World;
struct wmWindow;
struct wmWindowManager;
class StringRef;
/* `render_ops.cc` */
void ED_operatortypes_render();
/* `render_update.cc` */
void ED_render_engine_changed(Main *bmain, bool update_scene_data);
void ED_render_engine_area_exit(Main *bmain, ScrArea *area);
void ED_render_view_layer_changed(Main *bmain, bScreen *screen);
/* Callbacks handling data update events coming from depsgraph. */
void ED_render_id_flush_update(const DEGEditorUpdateContext *update_ctx, ID *id);
/**
* Update all 3D viewport render and draw engines on changes to the scene.
* This is called by the dependency graph when it detects changes.
*/
void ED_render_scene_update(const DEGEditorUpdateContext *update_ctx, bool updated);
/**
* Update 3D viewport render or draw engine on changes to the scene or view settings.
*/
void ED_render_view3d_update(Depsgraph *depsgraph, wmWindow *window, ScrArea *area, bool updated);
Scene *ED_render_job_get_scene(const bContext *C);
Scene *ED_render_job_get_current_scene(const bContext *C);
/**
* Render the preview method.
*/
enum ePreviewRenderMethod {
/** Preview is rendered for buttons window. */
PR_BUTS_RENDER = 0,
/** Preview is rendered for icons. hopefully fast enough for at least 32x32. */
PR_ICON_RENDER = 1,
/** No render, we just ensure deferred icon data gets generated. */
PR_ICON_DEFERRED = 2,
};
bool ED_check_engine_supports_preview(const Scene *scene);
const char *ED_preview_collection_name(ePreviewType pr_type);
void ED_preview_ensure_dbase(bool with_gpencil);
void ED_preview_free_dbase();
/**
* For preview icons loaded from disk (deferred loading), use the size of the source image, and
* only scale to the display size when drawing. Then we actually know the final display size
* (so we don't scale twice), and can scale on the GPU while drawing.
*/
bool ED_preview_use_image_size(const PreviewImage *preview, eIconSizes size);
/**
* Check if \a id is supported by the automatic preview render.
*/
bool ED_preview_id_render_is_supported(const ID *id, const char **r_disabled_hint = nullptr);
void ED_preview_set_visibility(Main *pr_main,
Scene *scene,
ViewLayer *view_layer,
ePreviewType pr_type,
ePreviewRenderMethod pr_method);
World *ED_preview_prepare_world(Main *pr_main,
const Scene *scene,
const World *world,
ID_Type id_type,
ePreviewRenderMethod pr_method);
World *ED_preview_prepare_world_simple(Main *bmain);
void ED_preview_world_simple_set_rgb(World *world, const float color[4]);
void ED_preview_shader_job(const bContext *C,
const void *owner,
ID *id,
ID *parent,
MTex *slot,
int sizex,
int sizey,
ePreviewRenderMethod method);
void ED_preview_icon_render(
const bContext *C, Scene *scene, PreviewImage *prv_img, ID *id, enum eIconSizes icon_size);
void ED_preview_icon_job(
const bContext *C, PreviewImage *prv_img, ID *id, enum eIconSizes icon_size, bool delay);
/**
* ID previews may be generated in a parallel job. The operation that generates the preview
* likely does an undo push before the preview is actually done and stored in the ID. The
* restart system exists to make sure previews remain up to date.
*
* When undoing back to the moment the preview generation was triggered, this function
* schedules the preview for regeneration.
*/
void ED_preview_restart_work(const bContext *C);
void ED_preview_kill_jobs(wmWindowManager *wm, Main *bmain);
void ED_preview_kill_jobs_for_id(wmWindowManager *wm, const ID *id);
/**
* Inform the preview system that a preview was requested for download. Should be called right
* before a download request is done, so the downloading status is made known to the preview
* system.
*
* This needs to be called regardless of the loading/loaded status of the preview; it doesn't
* matter whether or not it was already loaded, or will be requested to be loaded, from disk.
*/
void ED_preview_online_download_requested(StringRef preview_full_filepath);
/**
* Inform the preview system that a preview has finished downloading (successfully or not) meaning
* the preview may be available on disk (and if it doesn't exist on disk, it won't appear without
* requesting a download again).
*/
void ED_preview_online_download_finished(wmWindowManager *wm, StringRef preview_full_filepath);
void ED_preview_draw(
const bContext *C, void *idp, void *parentp, void *slotp, uiPreview *ui_preview, rcti *rect);
/**
* For UI previews (i.e. #uiPreview, not #PreviewImage): Tag all previews for \a id as dirty, so
* the next redraw triggers a re-render in #ED_preview_draw().
*/
void ED_previews_tag_dirty_by_id(const Main &bmain, const ID &id);
void ED_render_clear_mtex_copybuf();
void ED_render_internal_init();
} // namespace blender

View File

@@ -0,0 +1,87 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
#include "BLI_compiler_attrs.h"
#include "BKE_scene.hh"
namespace blender {
struct ReportList;
struct bContext;
struct wmWindow;
struct Strip;
Scene *ED_scene_add(Main *bmain, bContext *C, wmWindow *win, eSceneCopyMethod method)
ATTR_NONNULL();
/**
* Add a new scene from the sequence editor.
*/
Scene *ED_scene_sequencer_add(Main *bmain, bContext *C, eSceneCopyMethod method);
/**
* \note Only call outside of area/region loops.
* \return true if successful.
*/
bool ED_scene_delete(bContext *C, Main *bmain, Scene *scene) ATTR_NONNULL();
/**
* Replace the given scene (assumed to be an active scene) by another suitable one.
*
* Checks if the given active scene can actually be deleted.
*
* Also ensures that all needed updates in WM and UI code is done.
*
* \param scene: The scene to be replaced, often the active scene but may be any scene.
* \param scene_new: When non-null, this scene is used as a replacement for `scene`.
* Otherwise, #BKE_scene_find_replacement() is used to find a replacement.
* \return true if the given `scene` was successfully replaced and can safely be deleted.
*/
bool ED_scene_replace_active_for_deletion(bContext &C,
Main &bmain,
Scene &scene,
Scene *scene_new = nullptr);
/**
* Depsgraph updates after scene becomes active in a window.
*/
void ED_scene_change_update(Main *bmain, Scene *scene, ViewLayer *layer) ATTR_NONNULL();
bool ED_scene_view_layer_delete(Main *bmain, Scene *scene, ViewLayer *layer, ReportList *reports)
ATTR_NONNULL(1, 2, 3);
void ED_operatortypes_scene();
/* -------------------------------------------------------------------- */
/** \name Scene FPS Management
* \{ */
struct SceneFPS_State {
float fps_average;
float fps_target;
bool fps_target_is_fractional;
};
/**
* Update frame rate info for viewport drawing.
* \param ltime: Time since the last update,
* compatible with the result of #BLI_time_now_seconds.
*/
void ED_scene_fps_average_accumulate(Scene *scene, short fps_samples, double ltime)
ATTR_NONNULL(1);
/**
* Calculate an average (if it's not already calculated).
* \return false on failure otherwise all values in `state` are initialized.
*/
bool ED_scene_fps_average_calc(const Scene *scene, SceneFPS_State *r_state) ATTR_NONNULL(1, 2);
/**
* Clear run-time data for accumulating animation playback average times.
*/
void ED_scene_fps_average_clear(Scene *scene) ATTR_NONNULL(1);
/** \} */
} // namespace blender

View File

@@ -0,0 +1,820 @@
/* SPDX-FileCopyrightText: 2008 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
#include "DNA_userdef_types.h"
#include "DNA_workspace_types.h"
#include "ED_screen_types.hh"
#include "WM_types.hh"
#include "BLI_compiler_attrs.h"
namespace blender {
struct ARegion;
struct AZone;
struct Depsgraph;
struct IDProperty;
struct Main;
struct MenuType;
struct Scene;
struct SpaceLink;
struct WorkSpace;
struct WorkSpaceInstanceHook;
struct bContext;
struct bScreen;
struct rcti;
struct wmKeyConfig;
struct wmMsgSubscribeKey;
struct wmMsgSubscribeValue;
struct wmNotifier;
struct wmOperatorType;
struct wmRegionListenerParams;
struct wmRegionMessageSubscribeParams;
struct wmSpaceTypeListenerParams;
struct wmWindow;
struct wmWindowManager;
namespace ui {
struct Layout;
struct Block;
enum class ButtonSectionsAlign : int8_t;
} // namespace ui
/* regions */
/** Only exported for WM. */
void ED_region_do_listen(wmRegionListenerParams *params);
/** Only exported for WM. */
void ED_region_do_layout(bContext *C, ARegion *region);
/** Only exported for WM. */
void ED_region_do_draw(bContext *C, ARegion *region);
void ED_region_exit(bContext *C, ARegion *region);
/**
* Utility to exit and free an area-region. Screen level regions (menus/popups) need to be treated
* slightly differently, see #ui::region_temp_remove().
*/
void ED_region_remove(bContext *C, ScrArea *area, ARegion *region);
void ED_region_pixelspace(const ARegion *region);
/**
* Call to move a popup window (keep OpenGL context free!)
*/
void ED_region_update_rect(ARegion *region);
/**
* Externally called for floating regions like menus.
*/
void ED_region_floating_init(ARegion *region);
void ED_region_tag_redraw(ARegion *region);
void ED_region_tag_redraw_partial(ARegion *region, const rcti *rct, bool rebuild);
void ED_region_tag_redraw_cursor(ARegion *region);
void ED_region_tag_redraw_no_rebuild(ARegion *region);
void ED_region_tag_refresh_ui(ARegion *region);
/**
* Tag editor overlays to be redrawn. If in doubt about which parts need to be redrawn (partial
* clipping rectangle set), redraw everything.
*/
void ED_region_tag_redraw_editor_overlays(ARegion *region);
/**
* If the region has tag RGN_FLAG_INDICATE_OVERFLOW then draw
* a line or gradient on edges if there is content overflowing.
*/
void ED_region_draw_overflow_indication(const ScrArea *area,
const ARegion *region,
const rcti *mask = nullptr);
/**
* Set the temporary update flag for property search.
*/
void ED_region_search_filter_update(const ScrArea *area, ARegion *region);
/**
* Returns the search string if the space type and region type support property search.
*/
const char *ED_area_region_search_filter_get(const ScrArea *area, const ARegion *region);
/**
* Returns the maximum size a region can grow to so it still fits in the area.
*/
int ED_area_max_regionsize(const ScrArea *area, const ARegion *scale_region, const AZEdge edge);
void ED_region_panels_init(wmWindowManager *wm, ARegion *region);
void ED_region_panels_ex(const bContext *C,
ARegion *region,
wm::OpCallContext op_context,
const char *contexts[]);
void ED_region_panels(const bContext *C, ARegion *region);
/**
* \param contexts: A NULL terminated array of context strings to match against.
* Matching against any of these strings will draw the panel.
* Can be NULL to skip context checks.
*/
void ED_region_panels_layout_ex(const bContext *C,
ARegion *region,
ListBaseT<PanelType> *paneltypes,
wm::OpCallContext op_context,
const char *contexts[],
const char *category_override);
/**
* Build the same panel list as #ED_region_panels_layout_ex and checks whether any
* of the panels contain a search result based on the area / region's search filter.
*/
bool ED_region_property_search(const bContext *C,
ARegion *region,
ListBaseT<PanelType> *paneltypes,
const char *contexts[],
const char *category_override);
void ED_region_panels_layout(const bContext *C, ARegion *region);
void ED_region_panels_draw(const bContext *C, ARegion *region);
void ED_region_header_init(ARegion *region);
void ED_region_header(const bContext *C, ARegion *region);
void ED_region_header_layout(const bContext *C, ARegion *region);
void ED_region_header_draw(const bContext *C, ARegion *region);
/** Version of #ED_region_header() that draws with button sections. */
void ED_region_header_with_button_sections(const bContext *C,
ARegion *region,
ui::ButtonSectionsAlign align);
/** Version of #ED_region_header_draw() that draws with button sections. */
void ED_region_header_draw_with_button_sections(const bContext *C,
const ARegion *region,
ui::ButtonSectionsAlign align);
void ED_region_cursor_set(wmWindow *win, ScrArea *area, ARegion *region);
/**
* Exported to all editors, uses fading default.
*/
void ED_region_toggle_hidden(bContext *C, ARegion *region);
/**
* For use after changing visibility of regions.
*/
void ED_region_visibility_change_update_ex(
bContext *C, ScrArea *area, ARegion *region, bool is_hidden, bool do_init);
void ED_region_visibility_change_update(bContext *C, ScrArea *area, ARegion *region);
/* `screen_ops.cc` */
/**
* \note Assumes that \a region itself is not a split version from previous region.
*/
void ED_region_visibility_change_update_animated(bContext *C, ScrArea *area, ARegion *region);
void ED_region_clear(const bContext *C, const ARegion *region, int /*ThemeColorID*/ colorid);
void ED_region_info_draw(ARegion *region,
const char *text,
const float fill_color[4],
bool full_redraw);
void ED_region_info_draw_multiline(ARegion *region,
const char *text_array[],
const float fill_color[4],
bool full_redraw);
void ED_region_image_metadata_panel_draw(ImBuf *ibuf, ui::Layout *layout);
void ED_region_grid_draw(ARegion *region, float zoomx, float zoomy, float x0, float y0);
float ED_region_blend_alpha(ARegion *region);
const rcti *ED_region_visible_rect(ARegion *region);
/**
* Overlapping regions only in the following restricted cases.
*/
bool ED_region_is_overlap(int spacetype, int regiontype);
int ED_region_snap_size_test(const ARegion *region);
bool ED_region_snap_size_apply(ARegion *region, int snap_flag);
/* message_bus callbacks */
void ED_region_do_msg_notify_tag_redraw(bContext *C,
wmMsgSubscribeKey *msg_key,
wmMsgSubscribeValue *msg_val);
void ED_area_do_msg_notify_tag_refresh(bContext *C,
wmMsgSubscribeKey *msg_key,
wmMsgSubscribeValue *msg_val);
/**
* Follow #ARegionType.message_subscribe.
*/
void ED_area_do_mgs_subscribe_for_tool_header(const wmRegionMessageSubscribeParams *params);
void ED_area_do_mgs_subscribe_for_tool_ui(const wmRegionMessageSubscribeParams *params);
/* message bus */
/**
* Generate subscriptions for this region.
*/
void ED_region_message_subscribe(wmRegionMessageSubscribeParams *params);
/* spaces */
/**
* \note Keymap definitions are registered only once per WM initialize,
* usually on file read, using the keymap the actual areas/regions add the handlers.
* \note Called in `wm.cc`. */
void ED_spacetypes_keymap(wmKeyConfig *keyconf);
/**
* Returns offset for next button in header.
*/
int ED_area_header_switchbutton(const bContext *C, ui::Block *block, int yco);
/* areas */
/**
* Ensure #ScrArea.type and #ARegion.type are set and valid.
*/
void ED_area_and_region_types_init(ScrArea *area);
/**
* Called in screen_refresh, or screens_init, also area size changes.
*/
void ED_area_init(bContext *C, const wmWindow *win, ScrArea *area);
void ED_area_exit(bContext *C, ScrArea *area);
StringRefNull ED_area_name(const ScrArea *area);
int ED_area_icon(const ScrArea *area);
int ED_screen_area_active(const bContext *C);
void ED_screen_global_areas_refresh(wmWindow *win);
void ED_screen_global_areas_sync(wmWindow *win);
/** Only exported for WM. */
void ED_area_do_listen(wmSpaceTypeListenerParams *params);
void ED_area_tag_redraw(ScrArea *area);
void ED_area_tag_redraw_no_rebuild(ScrArea *area);
void ED_area_tag_redraw_regiontype(ScrArea *area, int regiontype);
void ED_area_tag_refresh(ScrArea *area);
/**
* For regions that change the region size in their #ARegionType.layout() callback: Mark the area
* as having a changed region size, requiring refitting of regions within the area.
*/
void ED_area_tag_region_size_update(ScrArea *area, ARegion *changed_region);
/**
* Only exported for WM.
*/
void ED_area_do_refresh(bContext *C, ScrArea *area);
AZone *ED_area_azones_update(ScrArea *area, const int mouse_xy[2]);
/**
* Show the given text in the area's header, instead of its regular contents.
* Use NULL to disable this and show the regular header contents again.
*/
void ED_area_status_text(ScrArea *area, const char *str);
/**
* \param skip_region_exit: Skip calling area exit callback. Set for opening temp spaces.
*/
void ED_area_newspace(bContext *C, ScrArea *area, int type, bool skip_region_exit);
void ED_area_prevspace(bContext *C, ScrArea *area);
void ED_area_swapspace(bContext *C, ScrArea *sa1, ScrArea *sa2);
int ED_area_headersize();
int ED_area_footersize();
/**
* \return the final height of a global \a area, accounting for DPI.
*/
int ED_area_global_size_y(const ScrArea *area);
int ED_area_global_min_size_y(const ScrArea *area);
int ED_area_global_max_size_y(const ScrArea *area);
bool ED_area_is_global(const ScrArea *area);
/**
* For now we just assume all global areas are made up out of horizontal bars
* with the same size. A fixed size could be stored in ARegion instead if needed.
*
* \return the DPI aware height of a single bar/region in global areas.
*/
int ED_region_global_size_y();
void ED_area_update_region_sizes(wmWindowManager *wm, wmWindow *win, ScrArea *area);
bool ED_area_has_shared_border(ScrArea *a, ScrArea *b);
ScrArea *ED_area_offscreen_create(wmWindow *win, eSpace_Type space_type);
void ED_area_offscreen_free(wmWindowManager *wm, wmWindow *win, ScrArea *area);
/**
* Search all screens, even non-active or overlapping (multiple windows), return the most-likely
* area of interest. xy is relative to active window, like all similar functions.
*/
ScrArea *ED_area_find_under_cursor(const bContext *C, int spacetype, const int event_xy[2]);
ScrArea *ED_screen_areas_iter_first(const wmWindow *win, const bScreen *screen);
ScrArea *ED_screen_areas_iter_next(const bScreen *screen, const ScrArea *area);
/**
* Iterate over all areas visible in the screen (screen as in everything
* visible in the window, not just bScreen).
* \note Skips global areas with flag GLOBAL_AREA_IS_HIDDEN.
*/
#define ED_screen_areas_iter(win, screen, area_name) \
for (ScrArea *area_name = ED_screen_areas_iter_first(win, screen); area_name != NULL; \
area_name = ED_screen_areas_iter_next(screen, area_name))
#define ED_screen_verts_iter(win, screen, vert_name) \
for (ScrVert *vert_name = (win)->global_areas.vertbase.first ? \
(ScrVert *)(win)->global_areas.vertbase.first : \
(ScrVert *)(screen)->vertbase.first; \
vert_name != NULL; \
vert_name = (vert_name == (win)->global_areas.vertbase.last) ? \
(ScrVert *)(screen)->vertbase.first : \
vert_name->next)
/**
* Update all areas that are supposed to follow the timeline current-frame indicator.
*/
void ED_areas_do_frame_follow(bContext *C, bool center_view);
/* screens */
/**
* File read, set all screens, ....
*/
void ED_screens_init(bContext *C, Main *bmain, wmWindowManager *wm);
/**
* Only for edge lines between areas.
*/
void ED_screen_draw_edges(wmWindow *win);
/**
* Make this screen usable.
* for file read and first use, for scaling window, area moves.
*/
void ED_screen_refresh(bContext *C, wmWindowManager *wm, wmWindow *win);
void ED_screen_ensure_updated(bContext *C, wmWindowManager *wm, wmWindow *win);
void ED_screen_do_listen(bContext *C, const wmNotifier *note);
/**
* \brief Change the active screen.
*
* Operator call, WM + Window + screen already existed before
*
* \warning Do NOT call in area/region queues!
* \returns if screen changing was successful.
*/
bool ED_screen_change(bContext *C, bScreen *screen);
void ED_screen_scene_change(bContext *C, wmWindow *win, Scene *scene, bool refresh_toolsystem);
/**
* Called in `wm_event_system.cc`. sets state vars in screen, cursors.
* event type is mouse move.
*/
void ED_screen_set_active_region(bContext *C, wmWindow *win, const int xy[2]);
void ED_screen_exit(bContext *C, wmWindow *window, bScreen *screen);
/**
* redraws: uses defines from `stime->redraws`
* \param enable: 1 - forward on, -1 - backwards on, 0 - off.
*/
void ED_screen_animation_timer(
bContext *C, Scene *scene, ViewLayer *view_layer, int redraws, int sync, int enable);
/**
* Remove the animation timer, same as calling ED_screen_animation_timer(..., enable=0).
*/
void ED_screen_animation_timer_remove(wmWindowManager *wm, wmWindow *win);
void ED_screen_animation_timer_update(bScreen *screen, int redraws);
/**
* Stop the animation in all screens where should_stop_fn(screen) returns true.
*
* The callback is only called for screens that have an animation timer.
*/
void ED_screen_animation_stop(Main *bmain,
wmWindowManager *wm,
FunctionRef<bool(const bScreen &screen)> should_stop_fn);
void ED_screen_restore_temp_type(bContext *C, ScrArea *area);
ScrArea *ED_screen_full_newspace(bContext *C, ScrArea *area, int type);
/**
* \a was_prev_temp for the case previous space was a temporary full-screen as well
*/
void ED_screen_full_prevspace(bContext *C, ScrArea *area);
/**
* Restore a screen / area back to default operation, after temp full-screen modes.
*/
void ED_screen_full_restore(bContext *C, ScrArea *area);
/**
* Create a new temporary screen with a maximized, empty area.
* This can be closed with #ED_screen_state_toggle().
*
* Use this to just create a new maximized screen/area, rather than maximizing an existing one.
* Otherwise, maximize with #ED_screen_state_toggle().
*/
bScreen *ED_screen_state_maximized_create(bContext *C);
/**
* This function toggles: if area is maximized/full then the parent will be restored.
*
* Use #ED_screen_state_maximized_create() if you do not want the toggle behavior when changing to
* a maximized area. I.e. if you just want to open a new maximized screen/area, not maximize a
* specific area. In the former case, space data of the maximized and non-maximized area should be
* independent, in the latter it should be the same.
*
* \warning \a area may be freed.
*/
ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *area, eScreen_State state);
/**
* Wrapper to open a temporary space either as full-screen space, or as separate window,
* as defined by \a display_type.
*
* \param title: Title to set for the window, if a window is spawned.
*/
ScrArea *ED_screen_temp_space_open(bContext *C,
const char *title,
eSpace_Type space_type,
int display_type,
bool dialog) ATTR_NONNULL(1);
void ED_screens_header_tools_menu_create(bContext *C, ui::Layout *layout, void *arg);
void ED_screens_footer_tools_menu_create(bContext *C, ui::Layout *layout, void *arg);
void ED_screens_region_flip_menu_create(bContext *C, ui::Layout *layout, void *arg);
/**
* \return true if any active area requires to see in 3D.
*/
bool ED_screen_stereo3d_required(const bScreen *screen, const Scene *scene);
Scene *ED_screen_scene_find(const bScreen *screen, const wmWindowManager *wm);
/**
* Find the scene displayed in \a screen.
* \note Assumes \a screen to be visible/active!
*/
Scene *ED_screen_scene_find_with_window(const bScreen *screen,
const wmWindowManager *wm,
wmWindow **r_window);
ScrArea *ED_screen_area_find_with_spacedata(const bScreen *screen,
const SpaceLink *sl,
bool only_visible);
wmWindow *ED_screen_window_find(const bScreen *screen, const wmWindowManager *wm);
/* workspaces */
WorkSpace *ED_workspace_add(Main *bmain, const char *name) ATTR_NONNULL();
/**
* \brief Change the active workspace.
*
* Operator call, WM + Window + screen already existed before
* Pretty similar to #ED_screen_change since changing workspace also changes screen.
*
* \warning Do NOT call in area/region queues!
* \returns if workspace changing was successful.
*/
bool ED_workspace_change(WorkSpace *workspace_new, bContext *C, wmWindowManager *wm, wmWindow *win)
ATTR_NONNULL();
/**
* Duplicate a workspace including its layouts. Does not activate the workspace, but
* it stores the screen-layout to be activated (BKE_workspace_temp_layout_store)
*/
WorkSpace *ED_workspace_duplicate(WorkSpace *workspace_old, Main *bmain, wmWindow *win);
/**
* \return if succeeded.
*/
bool ED_workspace_delete(WorkSpace *workspace, Main *bmain, bContext *C, wmWindowManager *wm)
ATTR_NONNULL();
/**
* Some editor data may need to be synced with scene data (3D View camera and layers).
* This function ensures data is synced for editors in active layout of \a workspace.
*/
void ED_workspace_scene_data_sync(WorkSpaceInstanceHook *hook, Scene *scene) ATTR_NONNULL();
/**
* Make sure there is a non-full-screen layout to switch to that isn't used yet by an other window.
* Needed for workspace or screen switching to ensure valid screens.
*
* \param layout_fallback_base: As last resort, this layout is duplicated and returned.
*/
WorkSpaceLayout *ED_workspace_screen_change_ensure_unused_layout(
Main *bmain,
WorkSpace *workspace,
WorkSpaceLayout *layout_new,
const WorkSpaceLayout *layout_fallback_base,
wmWindow *win) ATTR_NONNULL();
/**
* Empty screen, with 1 dummy area without space-data. Uses window size.
*/
WorkSpaceLayout *ED_workspace_layout_add(Main *bmain,
WorkSpace *workspace,
wmWindow *win,
const char *name) ATTR_NONNULL();
WorkSpaceLayout *ED_workspace_layout_duplicate(Main *bmain,
WorkSpace *workspace,
const WorkSpaceLayout *layout_old,
wmWindow *win) ATTR_NONNULL();
/**
* \warning Only call outside of area/region loops!
* \return true if succeeded.
*/
bool ED_workspace_layout_delete(WorkSpace *workspace, WorkSpaceLayout *layout_old, bContext *C)
ATTR_NONNULL();
bool ED_workspace_layout_cycle(WorkSpace *workspace, short direction, bContext *C) ATTR_NONNULL();
void ED_workspace_status_text(bContext *C, const char *str);
class WorkspaceStatus {
WorkSpace *workspace_;
wmWindowManager *wm_;
public:
WorkspaceStatus(bContext *C);
/**
* Add a static status entry and up to two icons.
*
* Example:
* [LMB][Enter] Confirm
*/
void item(std::string text, int icon1, int icon2 = 0);
/**
* Add extra (or negative) space between items.
*/
void separator(float factor = 1.0f);
/**
* Add a dynamic status entry with up to two icons that change appearance.
* Example:
* [CTRL] Tweak
*/
void item_bool(std::string text, bool inverted, int icon1, int icon2 = 0);
/**
* Add a static status entry showing two icons separated by a dash.
* Example:
* [A]-[Z] Search
*/
void range(std::string text, int icon1, int icon2);
/**
* Add a dynamic status entry for a given property in an operator's keymap.
* Example:
* [V] X-Ray
*/
void opmodal(std::string text, const wmOperatorType *ot, int propvalue, bool inverted = false);
};
void ED_workspace_do_listen(bContext *C, const wmNotifier *note);
/* anim */
/**
* Results in fully updated anim system.
*/
void ED_update_for_newframe(Main *bmain, Depsgraph *depsgraph);
/**
* Toggle operator.
*/
void ED_reset_audio_device(bContext *C);
wmOperatorStatus ED_screen_animation_play(bContext *C, int sync, int mode);
/**
* Find window that owns the animation timer.
*/
wmWindow *ED_window_animation_playing_no_scrub(const wmWindowManager *wm);
bScreen *ED_screen_animation_playing(const wmWindowManager *wm);
bScreen *ED_screen_animation_no_scrub(const wmWindowManager *wm);
/**
* Find the scene that is currently playing in a window/screen.
*/
Scene *ED_screen_find_playing_scene(const bScreen *screen, bool scrub = false);
/* screen keymaps */
/* called in `spacetypes.cc`. */
void ED_operatortypes_screen();
/* called in `spacetypes.cc`. */
void ED_keymap_screen(wmKeyConfig *keyconf);
/**
* Workspace key-maps.
*/
void ED_operatortypes_workspace();
/* operators; context poll callbacks */
bool ED_operator_screenactive(bContext *C);
bool ED_operator_active_screen_and_scene(bContext *C);
bool ED_operator_screenactive_nobackground(bContext *C);
/**
* When mouse is over area-edge.
*/
bool ED_operator_screen_mainwinactive(bContext *C);
bool ED_operator_areaactive(bContext *C);
bool ED_operator_regionactive(bContext *C);
bool ED_operator_scene(bContext *C);
bool ED_operator_scene_editable(bContext *C);
bool ED_operator_sequencer_scene(bContext *C);
bool ED_operator_sequencer_scene_editable(bContext *C);
bool ED_operator_objectmode(bContext *C);
/**
* Same as #ED_operator_objectmode() but additionally sets a "disabled hint". That is, a message
* to be displayed to the user explaining why the operator can't be used in current context.
*/
bool ED_operator_objectmode_poll_msg(bContext *C);
bool ED_operator_objectmode_with_view3d_poll_msg(bContext *C);
bool ED_operator_view3d_active(bContext *C);
bool ED_operator_region_view3d_active(bContext *C);
bool ED_operator_region_gizmo_active(bContext *C);
/**
* Generic for any view2d which uses anim_ops.
*/
bool ED_operator_animview_active(bContext *C);
bool ED_operator_region_animview_active(bContext *C);
bool ED_operator_outliner_active(bContext *C);
bool ED_operator_region_outliner_active(bContext *C);
bool ED_operator_outliner_active_no_editobject(bContext *C);
/**
* \note Will return true for file spaces in either file or asset browsing mode! See
* #ED_operator_file_browsing_active() (file browsing only) and
* #ED_operator_asset_browsing_active() (asset browsing only).
*/
bool ED_operator_file_active(bContext *C);
bool ED_operator_region_file_active(bContext *C);
/**
* \note Will only return true if the file space is in file browsing mode, not asset browsing! See
* #ED_operator_file_active() (file or asset browsing) and
* #ED_operator_asset_browsing_active() (asset browsing only).
*/
bool ED_operator_file_browsing_active(bContext *C);
bool ED_operator_asset_browsing_active(bContext *C);
bool ED_operator_spreadsheet_active(bContext *C);
bool ED_operator_action_active(bContext *C);
bool ED_operator_region_action_active(bContext *C);
bool ED_operator_buttons_active(bContext *C);
bool ED_operator_node_active(bContext *C);
bool ED_operator_node_editable(bContext *C);
bool ED_operator_graphedit_active(bContext *C);
bool ED_operator_region_graphedit_active(bContext *C);
bool ED_operator_sequencer_active(bContext *C);
bool ED_operator_sequencer_active_editable(bContext *C);
bool ED_operator_image_active(bContext *C);
bool ED_operator_nla_active(bContext *C);
bool ED_operator_region_nla_active(bContext *C);
bool ED_operator_info_active(bContext *C);
bool ED_operator_region_info_active(bContext *C);
bool ED_operator_console_active(bContext *C);
bool ED_operator_preferences_active(bContext *C);
/** Only check there is an active object (no visibility check). */
bool ED_operator_object_active_only(bContext *C);
bool ED_operator_object_active(bContext *C);
bool ED_operator_object_active_objectmode(bContext *C);
bool ED_operator_object_active_editable_ex(bContext *C, const Object *ob);
bool ED_operator_object_active_editable(bContext *C);
/** Use in cases where it's essential the object is the active object in the current view layer. */
bool ED_operator_object_active_only_from_view_layer(bContext *C);
bool ED_operator_object_active_from_view_layer(bContext *C);
/**
* Object must be editable and fully local (i.e. not an override).
*/
bool ED_operator_object_active_local_editable_ex(bContext *C, const Object *ob);
bool ED_operator_object_active_local_editable(bContext *C);
bool ED_operator_object_active_editable_mesh(bContext *C);
bool ED_operator_object_active_editable_obdata_from_view_layer_ex(bContext *C, short obtype);
bool ED_operator_object_active_editable_mesh_from_view_layer(bContext *C);
bool ED_operator_object_active_editable_font(bContext *C);
bool ED_operator_editable_mesh(bContext *C);
bool ED_operator_editmesh(bContext *C);
bool ED_operator_editmesh_view3d(bContext *C);
bool ED_operator_editmesh_region_view3d(bContext *C);
bool ED_operator_editarmature(bContext *C);
bool ED_operator_editcurve(bContext *C);
bool ED_operator_editcurve_3d(bContext *C);
bool ED_operator_editsurf(bContext *C);
bool ED_operator_editsurfcurve(bContext *C);
bool ED_operator_editsurfcurve_region_view3d(bContext *C);
bool ED_operator_editfont(bContext *C);
bool ED_operator_editlattice(bContext *C);
bool ED_operator_editmball(bContext *C);
/**
* Wrapper for #ED_space_image_show_uvedit.
*/
bool ED_operator_uvedit(bContext *C);
bool ED_operator_uvedit_space_image(bContext *C);
bool ED_operator_uvmap(bContext *C);
bool ED_operator_posemode_exclusive(bContext *C);
/**
* Object must be editable, fully local (i.e. not an override), and exclusively in Pose mode.
*/
bool ED_operator_object_active_local_editable_posemode_exclusive(bContext *C);
/**
* Allows for pinned pose objects to be used in the object buttons
* and the non-active pose object to be used in the 3D view.
*/
bool ED_operator_posemode_context(bContext *C);
bool ED_operator_posemode(bContext *C);
bool ED_operator_posemode_local(bContext *C);
bool ED_operator_camera_poll(bContext *C);
/* `screen_user_menu.cc` */
bUserMenu **ED_screen_user_menus_find(const bContext *C, uint *r_len);
bUserMenu *ED_screen_user_menu_ensure(bContext *C);
/**
* Finds a menu item associated with an operator in user menus (aka Quick Favorites)
*
* \param op_prop_enum: name of an operator property when the operator is called with an enum (to
* be an empty string otherwise)
*/
bUserMenuItem_Op *ED_screen_user_menu_item_find_operator(ListBaseT<bUserMenuItem> *lb,
const wmOperatorType *ot,
IDProperty *prop,
const char *op_prop_enum,
wm::OpCallContext opcontext);
bUserMenuItem_Menu *ED_screen_user_menu_item_find_menu(ListBaseT<bUserMenuItem> *lb,
const MenuType *mt);
bUserMenuItem_Prop *ED_screen_user_menu_item_find_prop(ListBaseT<bUserMenuItem> *lb,
const char *context_data_path,
const char *prop_id,
int prop_index);
void ED_screen_user_menu_item_add_operator(ListBaseT<bUserMenuItem> *lb,
const char *ui_name,
const wmOperatorType *ot,
const IDProperty *prop,
const char *op_prop_enum,
wm::OpCallContext opcontext);
void ED_screen_user_menu_item_add_menu(ListBaseT<bUserMenuItem> *lb,
const char *ui_name,
const MenuType *mt);
void ED_screen_user_menu_item_add_prop(ListBaseT<bUserMenuItem> *lb,
const char *ui_name,
const char *context_data_path,
const char *prop_id,
int prop_index);
void ED_screen_user_menu_item_remove(ListBaseT<bUserMenuItem> *lb, bUserMenuItem *umi);
void ED_screen_user_menu_register();
/* Cache display helpers */
void ED_region_cache_draw_background(ARegion *region);
void ED_region_cache_draw_curfra_label(int framenr, float x, float y);
void ED_region_cache_draw_cached_segments(
ARegion *region, int num_segments, const int *points, int sfra, int efra);
/* `area_utils.cc` */
/**
* Callback for #ARegionType.message_subscribe
*/
void ED_region_generic_tools_region_message_subscribe(
const wmRegionMessageSubscribeParams *params);
/**
* Callback for #ARegionType.snap_size
*/
int ED_region_generic_tools_region_snap_size(const ARegion *region, int size, int axis);
int ED_region_generic_panel_region_snap_size(const ARegion *region, int size, int axis);
/* `area_query.cc` */
bool ED_region_overlap_isect_x(const ARegion *region, int event_x);
bool ED_region_overlap_isect_y(const ARegion *region, int event_y);
bool ED_region_overlap_isect_xy(const ARegion *region, const int event_xy[2]);
bool ED_region_overlap_isect_any_xy(const ScrArea *area, const int event_xy[2]);
bool ED_region_overlap_isect_x_with_margin(const ARegion *region, int event_x, int margin);
bool ED_region_overlap_isect_y_with_margin(const ARegion *region, int event_y, int margin);
bool ED_region_overlap_isect_xy_with_margin(const ARegion *region,
const int event_xy[2],
int margin);
bool ED_region_panel_category_gutter_calc_rect(const ARegion *region, rcti *r_region_gutter);
bool ED_region_panel_category_gutter_isect_xy(const ARegion *region, const int event_xy[2]);
/**
* \note This may return true for multiple overlapping regions.
* If it matters, check overlapped regions first (#ARegion.overlap).
*/
bool ED_region_contains_xy(const ARegion *region, const int event_xy[2]);
/**
* Similar to #BKE_area_find_region_xy() but when \a event_xy intersects an overlapping region,
* this returns the region that is visually under the cursor. E.g. when over the
* transparent part of the region, it returns the region underneath.
*
* The overlapping region is determined using the #ED_region_contains_xy() query.
*/
ARegion *ED_area_find_region_xy_visual(const ScrArea *area, int regiontype, const int event_xy[2]);
/* `interface_region_hud.cc` */
namespace ui {
ARegionType *ED_area_type_hud(int space_type);
void ED_area_type_hud_clear(wmWindowManager *wm, ScrArea *area_keep);
void ED_area_type_hud_ensure(bContext *C, ScrArea *area);
/**
* Lookup the region the operation was executed in, and which should be used to redo the
* operation. The lookup is based on the region type, so it can return a different region when the
* same region type is present multiple times.
*/
ARegion *ED_area_type_hud_redo_region_find(const ScrArea *area, const ARegion *hud_region);
} // namespace ui
/**
* Default key-maps, bit-flags (matches order of evaluation).
*/
enum {
ED_KEYMAP_UI = (1 << 1),
ED_KEYMAP_GIZMO = (1 << 2),
ED_KEYMAP_TOOL = (1 << 3),
ED_KEYMAP_VIEW2D = (1 << 4),
ED_KEYMAP_ANIMATION = (1 << 6),
ED_KEYMAP_FRAMES = (1 << 7),
ED_KEYMAP_HEADER = (1 << 8),
ED_KEYMAP_FOOTER = (1 << 9),
ED_KEYMAP_GPENCIL = (1 << 10),
ED_KEYMAP_NAVBAR = (1 << 11),
ED_KEYMAP_ASSET_SHELF = (1 << 12),
};
/** #SCREEN_OT_space_context_cycle direction. */
enum eScreenCycle {
SPACE_CONTEXT_CYCLE_PREV,
SPACE_CONTEXT_CYCLE_NEXT,
};
} // namespace blender

View File

@@ -0,0 +1,133 @@
/* SPDX-FileCopyrightText: 2008 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
#include "DNA_vec_types.h"
namespace blender {
struct ARegion;
struct Scene;
struct ViewLayer;
/* ----------------------------------------------------- */
/**
* For animation playback operator, stored in #bScreen.animtimer.customdata.
*/
struct ScreenAnimData {
/** Do not read from this, only for comparing if region exists. */
ARegion *region;
/* The Scene and the View Layer that the animation timer is playing. */
Scene *scene;
ViewLayer *view_layer;
/* For sequencer scenes, account for scene syncing during playback. */
bool do_scene_syncing;
short redraws;
/** Flags for playback */
short flag;
/** Frame that playback was started from */
int sfra;
/** Next frame to go to (when ANIMPLAY_FLAG_USE_NEXT_FRAME is set) */
int nextfra;
/** Used for frame dropping */
double lagging_frame_count;
/** Playback was invoked from animation editor */
bool from_anim_edit;
};
/** #ScreenAnimData.flag */
enum {
/** User-setting - frame range is played backwards. */
ANIMPLAY_FLAG_REVERSE = (1 << 0),
/** Temporary - playback just jumped to the start/end. */
ANIMPLAY_FLAG_JUMPED = (1 << 1),
/** Drop frames as needed to maintain frame-rate. */
ANIMPLAY_FLAG_SYNC = (1 << 2),
/** Don't drop frames (and ignore #SCE_FRAME_DROP flag). */
ANIMPLAY_FLAG_NO_SYNC = (1 << 3),
/** Use #ScreenAnimData::nextfra at next timer update. */
ANIMPLAY_FLAG_USE_NEXT_FRAME = (1 << 4),
};
/* ----------------------------------------------------- */
/** Enum for Action Zone Edges. Which edge of area is action zone. */
enum AZEdge {
/** Region located on the left, _right_ edge is action zone.
* Region minimized to the top left */
AE_RIGHT_TO_TOPLEFT,
/** Region located on the right, _left_ edge is action zone.
* Region minimized to the top right */
AE_LEFT_TO_TOPRIGHT,
/** Region located at the bottom, _top_ edge is action zone.
* Region minimized to the bottom right */
AE_TOP_TO_BOTTOMRIGHT,
/** Region located at the top, _bottom_ edge is action zone.
* Region minimized to the top left */
AE_BOTTOM_TO_TOPLEFT,
};
enum AZScrollDirection {
AZ_SCROLL_VERT,
AZ_SCROLL_HOR,
};
/** For editing areas/regions. */
struct AZone {
AZone *next, *prev;
ARegion *region;
int type;
union {
/** Region-AZone, which of the edges (only for #AZONE_REGION). */
AZEdge edge;
AZScrollDirection direction;
};
/** For drawing. */
short x1, y1, x2, y2;
/** For clip. */
rcti rect;
/** For fade in/out. */
float alpha;
};
/** Action-Zone Type: #AZone.type */
enum {
/**
* Corner widgets for:
* - Splitting areas.
* - Swapping areas (Ctrl).
* - Copying the area into a new window (Shift).
*/
AZONE_AREA = 1,
/**
* Use for region show/hide state:
* - When a region is collapsed, draw a handle to expose.
* - When a region is expanded, use the action zone to resize the region.
*/
AZONE_REGION,
/**
* Widget at the very center of the 3D Viewport Quad View for resizing.
*/
AZONE_REGION_QUAD,
/**
* Used when in editor full-screen draw a corner to return to normal mode.
*/
AZONE_FULLSCREEN,
/**
* Hot-spot #AZone around scroll-bars to show/hide them.
* Only show the scroll-bars when the cursor is close.
*/
AZONE_REGION_SCROLL,
};
} // namespace blender

View File

@@ -0,0 +1,122 @@
/* SPDX-FileCopyrightText: 2008 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
#include <cstddef>
namespace blender {
struct Depsgraph;
struct Main;
struct Mesh;
struct Object;
struct RegionView3D;
struct ReportList;
struct Scene;
struct UndoType;
struct UndoStep;
struct bContext;
struct wmKeyConfig;
struct wmOperator;
namespace ed::sculpt_paint {
void object_sculpt_mode_enter(Main &bmain,
Depsgraph &depsgraph,
Scene &scene,
Object &ob,
bool force_dyntopo,
ReportList *reports);
void object_sculpt_mode_enter(bContext *C, Depsgraph &depsgraph, ReportList *reports);
void object_sculpt_mode_exit(Main &bmain, Depsgraph &depsgraph, Scene &scene, Object &ob);
void object_sculpt_mode_exit(bContext *C, Depsgraph &depsgraph);
/* `sculpt.cc` */
/**
* Checks if the currently active shape key is able to be sculpted on.
*
* If the active shape key is either muted or locked, an error message will be reported, unless
* \a reports is null.
*
* \return false if the shape key cannot be modified.
*/
bool shape_key_check(const Object &ob, ReportList *reports);
void operatortypes_sculpt();
void keymap_sculpt(wmKeyConfig *keyconf);
/* `sculpt_transform.cc` */
void update_modal_transform(bContext *C, Object &ob);
void cancel_modal_transform(bContext *C, Object &ob);
void init_transform(bContext *C, Object &ob, const float mval_fl[2], const char *undo_name);
void end_transform(bContext *C, Object &ob);
/* `sculpt_undo.cc` */
namespace undo {
void register_type(UndoType *ut);
/**
* Pushes an undo step using the operator name. This is necessary for
* redo panels to work; operators that do not support that may use
* #geometry_begin_ex instead if so desired.
*/
void geometry_begin(const Scene &scene, Object &ob, const wmOperator *op);
void geometry_begin_ex(const Scene &scene, Object &ob, const char *name);
void geometry_end(Object &ob);
/**
* Undo for changes happening on a base mesh for multires sculpting.
* if there is no multi-res sculpt active regular undo is used.
*/
void push_multires_mesh_begin(bContext *C, const char *str);
void push_multires_mesh_end(bContext *C, const char *str);
size_t step_memory_size_get(UndoStep *step);
} // namespace undo
namespace face_set {
int find_next_available_id(const Mesh &object);
int find_next_available_id(Object &object);
void initialize_none_to_id(Mesh *mesh, int new_id);
int active_update_and_get(bContext *C, Object &ob, const float mval_fl[2]);
} // namespace face_set
/**
* Fills the entire object's active color attribute layer with the fill color.
*
* \return #true if successful.
*/
bool object_active_color_init(Object &ob, const float fill_color[4]);
/**
* Fully replace the sculpt mesh with a mesh outside of #Main. This implements various checks to
* avoid pushing full geometry-type undo steps when possible, allowing for better performance.
*
* \warning To avoid false negatives when detecting mesh changes, it is critical that the caller
* adds an owner to the attribute data arrays before modifying the original object's mesh. This
* allows constant time checks for whether the mesh has changed.
*/
void store_mesh_from_eval(const wmOperator &op,
const Scene &scene,
const Depsgraph &depsgraph,
const RegionView3D *rv3d,
Object &object,
Mesh *new_mesh);
} // namespace ed::sculpt_paint
} // namespace blender

View File

@@ -0,0 +1,119 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
#include <string>
#include "BLI_compiler_attrs.h"
namespace blender {
struct PointerRNA;
struct wmOperatorType;
template<typename CoordT> struct KDTree;
template<typename T, int Size> struct VecBase;
enum {
SEL_TOGGLE = 0,
SEL_SELECT = 1,
SEL_DESELECT = 2,
SEL_INVERT = 3,
};
enum WalkSelectDirection {
UI_SELECT_WALK_UP,
UI_SELECT_WALK_DOWN,
UI_SELECT_WALK_LEFT,
UI_SELECT_WALK_RIGHT,
};
/** See #WM_operator_properties_select_operation */
enum eSelectOp : int8_t {
SEL_OP_ADD = 1,
SEL_OP_SUB,
SEL_OP_SET,
SEL_OP_AND,
SEL_OP_XOR,
};
/** Select Similar. */
enum eSimilarCmp {
SIM_CMP_EQ = 0,
SIM_CMP_GT,
SIM_CMP_LT,
};
#define SEL_OP_USE_OUTSIDE(sel_op) (ELEM(sel_op, SEL_OP_AND))
#define SEL_OP_USE_PRE_DESELECT(sel_op) (ELEM(sel_op, SEL_OP_SET))
#define SEL_OP_CAN_DESELECT(sel_op) (!ELEM(sel_op, SEL_OP_ADD))
/**
* Use when we've de-selected all first for 'SEL_OP_SET'.
* 1: select, 0: deselect, -1: pass.
*/
int ED_select_op_action(eSelectOp sel_op, bool is_select, bool is_inside);
/**
* Use when we've de-selected all items first (for modes that need it).
*
* \note In some cases changing selection needs to perform other checks,
* so it's more straightforward to deselect all, then select.
*/
int ED_select_op_action_deselected(eSelectOp sel_op, bool is_select, bool is_inside);
bool ED_select_similar_compare_float(float delta, float thresh, eSimilarCmp compare);
bool ED_select_similar_compare_float_tree(const KDTree<float> *tree,
float length,
float thresh,
eSimilarCmp compare);
/**
* Utility to use for selection operations that run multiple times (circle select).
*/
eSelectOp ED_select_op_modal(eSelectOp sel_op, bool is_first);
/** Argument passed to picking functions. */
struct SelectPick_Params {
/**
* - #SEL_OP_ADD named "extend" from operators.
* - #SEL_OP_SUB named "deselect" from operators.
* - #SEL_OP_XOR named "toggle" from operators.
* - #SEL_OP_AND (never used for picking).
* - #SEL_OP_SET use when "extend", "deselect" and "toggle" are all disabled.
*/
eSelectOp sel_op = SEL_OP_SET;
/** Deselect all, even when there is nothing found at the cursor location. */
bool deselect_all = false;
/**
* When selecting an element that is already selected, do nothing (passthrough).
* don't even make it active.
* Use to implement tweaking to move the selection without first de-selecting.
*/
bool select_passthrough = false;
};
/**
* Utility to get #eSelectPickMode from booleans for convenience.
*/
eSelectOp ED_select_op_from_operator(PointerRNA *ptr) ATTR_WARN_UNUSED_RESULT;
/**
* Initialize `params` from `op`,
* these properties are defined by #WM_operator_properties_mouse_select.
*/
SelectPick_Params ED_select_pick_params_from_operator(PointerRNA *ptr) ATTR_NONNULL(1);
/**
* Get-name callback for #wmOperatorType.get_name, this is mainly useful so the selection
* action is shown in the status-bar.
*/
std::string ED_select_pick_get_name(wmOperatorType *ot, PointerRNA *ptr);
std::string ED_select_circle_get_name(wmOperatorType *ot, PointerRNA *ptr);
} // namespace blender

View File

@@ -0,0 +1,94 @@
/* SPDX-FileCopyrightText: 2009 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
#include "BLI_vector_set.hh"
namespace blender {
struct Scene;
struct Strip;
struct SpaceSeq;
struct bContext;
struct View2D;
namespace ed::vse {
enum eStripHandle {
STRIP_HANDLE_NONE,
STRIP_HANDLE_LEFT,
STRIP_HANDLE_RIGHT,
};
struct StripSelection {
/** Closest strip in the selection to the mouse cursor. */
Strip *strip1 = nullptr;
/** Farthest strip in the selection from the mouse cursor. */
Strip *strip2 = nullptr;
/** Handle of `strip1`. */
eStripHandle handle = STRIP_HANDLE_NONE;
};
void select_strip_single(Scene *scene, Strip *strip, bool deselect_all);
/**
* Iterates over a scene's strips and deselects all of them.
*
* \param scene: scene containing strips to be deselected.
* \return true if any strips were deselected; false otherwise.
*/
bool deselect_all_strips(const Scene *scene);
bool maskedit_mask_poll(bContext *C);
bool check_show_maskedit(SpaceSeq *sseq, Scene *scene);
bool maskedit_poll(bContext *C);
/**
* Are we displaying the seq output (not channels or histogram).
*/
bool check_show_imbuf(const SpaceSeq &sseq);
bool check_show_strip(const SpaceSeq &sseq);
/**
* Check if there is animation shown during playback.
*
* - Colors of color strips are displayed on the strip itself.
* - Backdrop is drawn.
*/
bool has_playback_animation(const Scene *scene);
void ED_operatormacros_sequencer();
Strip *special_preview_get();
void special_preview_set(bContext *C, const int mval[2]);
void special_preview_clear();
/**
* Returns collection with selected strips presented to user. If operation is done in preview,
* collection is limited to selected presented strips, that can produce image output at current
* frame.
*
* \param C: context
* \return collection of strips (`Strip`)
*/
VectorSet<Strip *> selected_strips_from_context(bContext *C);
StripSelection pick_strip_and_handle(const struct Scene *scene,
const View2D *v2d,
float mouse_co[2]);
bool can_select_handle(const Scene *scene, const Strip *strip, const View2D *v2d);
bool handle_is_selected(const Strip *strip, eStripHandle handle);
bool is_scene_time_sync_needed(const bContext &C);
/**
* Returns the scene strip (if any) that should be used for the scene synchronization feature.
* This is the top-most visible scene strip at the current time of the \a sequencer_scene.
*/
const Strip *get_scene_strip_for_time_sync(const Scene *sequencer_scene);
void sync_active_scene_and_time_with_scene_strip(bContext &C);
} // namespace ed::vse
} // namespace blender

View File

@@ -0,0 +1,15 @@
/* SPDX-FileCopyrightText: 2008 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
namespace blender {
void ED_operatortypes_sound();
} // namespace blender

View File

@@ -0,0 +1,81 @@
/* SPDX-FileCopyrightText: 2008 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
namespace blender {
struct ARegion;
struct ARegionType;
struct bContext;
/* Only called once on startup. storage is global in BKE kernel listbase. */
void ED_spacetypes_init();
void ED_spacemacros_init();
/* The plugin-able API for export to editors. */
/* -------------------------------------------------------------------- */
/** \name Calls for registering default spaces
*
* Calls for registering default spaces, only called once, from #ED_spacetypes_init
* \{ */
void ED_spacetype_outliner();
void ED_spacetype_view3d();
void ED_spacetype_ipo();
void ED_spacetype_image();
void ED_spacetype_node();
void ED_spacetype_buttons();
void ED_spacetype_info();
void ED_spacetype_file();
void ED_spacetype_action();
void ED_spacetype_nla();
void ED_spacetype_script();
void ED_spacetype_text();
void ED_spacetype_console();
void ED_spacetype_userpref();
void ED_spacetype_clip();
void ED_spacetype_statusbar();
void ED_spacetype_topbar();
namespace ed::vse {
void ED_spacetype_sequencer();
}
namespace ed::spreadsheet {
void register_spacetype();
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Space-type Static Data
* Calls for instancing and freeing space-type static data called in #WM_init_exit
* \{ */
void ED_file_init();
void ED_file_exit();
/** \} */
#define REGION_DRAW_POST_VIEW 0
#define REGION_DRAW_POST_PIXEL 1
#define REGION_DRAW_PRE_VIEW 2
#define REGION_DRAW_BACKDROP 3
void *ED_region_draw_cb_activate(ARegionType *art,
void (*draw)(const bContext *, ARegion *, void *),
void *customdata,
int type);
void ED_region_draw_cb_draw(const bContext *C, ARegion *region, int type);
void ED_region_surface_draw_cb_draw(const bContext *C, ARegionType *art, int type);
bool ED_region_draw_cb_exit(ARegionType *art, void *handle);
void ED_region_draw_cb_remove_by_type(ARegionType *art, void *draw_fn, void (*free)(void *));
} // namespace blender

View File

@@ -0,0 +1,21 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
namespace blender {
struct ID;
struct SpaceSpreadsheet;
struct SpreadsheetTable;
namespace ed::spreadsheet {
ID *get_current_id(const SpaceSpreadsheet *sspreadsheet);
SpreadsheetTable *get_active_table(SpaceSpreadsheet &sspreadsheet);
const SpreadsheetTable *get_active_table(const SpaceSpreadsheet &sspreadsheet);
} // namespace ed::spreadsheet
} // namespace blender

View File

@@ -0,0 +1,51 @@
/* SPDX-FileCopyrightText: 2009 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
namespace blender {
struct ARegion;
struct SpaceText;
struct Text;
struct UndoStep;
struct UndoType;
struct bContext;
/* `text_draw.cc` */
bool ED_text_activate_in_screen(bContext *C, Text *text);
int ED_space_text_visible_lines_get(const SpaceText *st);
/**
* Moves the view to the cursor location, also used to make sure the view isn't outside the file.
*/
void ED_space_text_scroll_to_cursor(SpaceText *st, ARegion *region, bool center);
/**
* Takes a cursor (row, character) and returns x,y pixel coords.
*/
bool ED_space_text_region_location_from_cursor(const SpaceText *st,
const ARegion *region,
const int cursor_co[2],
int r_pixel_co[2]);
/* `text_undo.cc` */
/** Export for ED_undo_sys. */
void ED_text_undosys_type(UndoType *ut);
/** Use operator system to finish the undo step. */
UndoStep *ED_text_undo_push_init(bContext *C);
/* `text_format.cc` */
const char *ED_text_format_comment_line_prefix(Text *text);
bool ED_text_is_syntax_highlight_supported(Text *text);
} // namespace blender

View File

@@ -0,0 +1,57 @@
/* SPDX-FileCopyrightText: 2019 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
namespace blender {
struct ARegion;
struct Scene;
struct ScrArea;
struct bContext;
struct bDopeSheet;
struct rcti;
struct wmEvent;
struct wmWindow;
void ED_time_scrub_draw_current_frame(const ARegion *region,
const Scene *scene,
bool display_seconds,
bool display_stalk = true,
bool clamp_playhead = false);
/**
* Draw the scrub area with numbers inside.
* \param display_seconds: Defines if the display is in seconds or in frames.
* \param base: Defines the base number from which the number distance is calculated.
* The distance is always a simple fraction or a multiple of that number.
*/
void ED_time_scrub_draw(const ARegion *region,
const Scene *scene,
bool display_seconds,
bool discrete_frames,
int base);
/**
* Scroll-bars shouldn't overlap the time scrub UI. So this returns a mask adjusted to exclude it,
* which can be passed to #view2d_scrollers_draw().
*
* \param scroller_mask: Typically #View2D.mask (or something smaller, if further parts have been
* masked out already).
*/
rcti ED_time_scrub_clamp_scroller_mask(const rcti &scroller_mask);
bool ED_time_scrub_event_in_region(const ARegion *region, const wmEvent *event);
/** Follow the #EventHandlerPoll function signature. */
bool ED_time_scrub_event_in_region_poll(const wmWindow *win,
const ScrArea *area,
const ARegion *region,
const wmEvent *event);
void ED_time_scrub_channel_search_draw(const bContext *C, ARegion *region, bDopeSheet *dopesheet);
void ED_time_scrub_region_rect_get(const ARegion *region, rcti *r_rect);
} // namespace blender

View File

@@ -0,0 +1,234 @@
/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
#include "BLI_math_vector_types.hh"
#include "BLI_sys_types.h"
namespace blender {
/* ******************* Registration Function ********************** */
struct ARegion;
struct bContext;
struct Main;
struct Scene;
struct ReportList;
struct TransformOrientation;
struct Object;
struct RegionView3D;
struct View3D;
struct ViewLayer;
struct wmGizmoGroupType;
struct wmKeyConfig;
struct wmOperatorType;
namespace ed::transform {
void keymap_transform(wmKeyConfig *keyconf);
void transform_operatortypes();
/* ******************** Macros & Prototypes *********************** */
/* MODE AND NUMINPUT FLAGS */
enum eTfmMode {
TFM_INIT = -1,
TFM_DUMMY,
TFM_TRANSLATION,
TFM_ROTATION,
TFM_RESIZE,
TFM_SKIN_RESIZE,
TFM_TOSPHERE,
TFM_SHEAR,
TFM_BEND,
TFM_SHRINKFATTEN,
TFM_TILT,
TFM_TRACKBALL,
TFM_PUSHPULL,
TFM_EDGE_CREASE,
TFM_VERT_CREASE,
TFM_MIRROR,
TFM_BONESIZE,
TFM_BONE_ENVELOPE,
TFM_CURVE_SHRINKFATTEN,
TFM_MASK_SHRINKFATTEN,
TFM_BONE_ROLL,
TFM_TIME_TRANSLATE,
TFM_TIME_SLIDE,
TFM_TIME_SCALE,
TFM_TIME_EXTEND,
/* TFM_TIME_DUPLICATE (deprecated). */
TFM_BAKE_TIME = 26,
TFM_DEPRECATED, /* was BEVEL */
TFM_BWEIGHT,
TFM_ALIGN,
TFM_EDGE_SLIDE,
TFM_VERT_SLIDE,
TFM_SEQ_SLIDE,
TFM_BONE_ENVELOPE_DIST,
TFM_NORMAL_ROTATION,
TFM_GPENCIL_OPACITY,
};
/**
* Standalone call to get the transformation center corresponding to the current situation
* returns 1 if successful, 0 otherwise (usually means there's no selection)
* (if false is returns, `cent3d` is unmodified).
*/
bool calculateTransformCenter(bContext *C, int centerMode, float cent3d[3], float cent2d[2]);
/* UNUSED */
// int BIF_snappingSupported(Object *obedit);
void BIF_clearTransformOrientation(bContext *C);
void BIF_removeTransformOrientation(bContext *C, TransformOrientation *target);
void BIF_removeTransformOrientationIndex(bContext *C, int index);
bool BIF_createTransformOrientation(bContext *C,
ReportList *reports,
const char *name,
bool use_view,
bool activate,
bool overwrite);
void BIF_selectTransformOrientation(bContext *C, TransformOrientation *target);
void ED_getTransformOrientationMatrix(const Main &bmain,
const Scene *scene,
ViewLayer *view_layer,
const View3D *v3d,
Object *ob,
Object *obedit,
short around,
float r_orientation_mat[3][3]);
int BIF_countTransformOrientation(const bContext *C);
/* to be able to add operator properties to other operators */
#define P_MIRROR (1 << 0)
#define P_MIRROR_DUMMY (P_MIRROR | (1 << 1))
#define P_PROPORTIONAL (1 << 2)
#define P_ORIENT_AXIS (1 << 3)
#define P_ORIENT_AXIS_ORTHO (1 << 4)
#define P_ORIENT_MATRIX (1 << 5)
#define P_SNAP (1 << 6)
#define P_GEO_SNAP (P_SNAP | (1 << 7))
#define P_ALIGN_SNAP (P_GEO_SNAP | (1 << 8))
#define P_CONSTRAINT (1 << 9)
#define P_OPTIONS (1 << 10)
#define P_CORRECT_UV (1 << 11)
#define P_NO_DEFAULTS (1 << 12)
#define P_NO_TEXSPACE (1 << 13)
#define P_CENTER (1 << 14)
#define P_GPENCIL_EDIT (1 << 15)
#define P_CURSOR_EDIT (1 << 16)
#define P_VIEW2D_EDGE_PAN (1 << 17)
/* For properties performed when confirming the transformation. */
#define P_POST_TRANSFORM (1 << 18)
#define P_TRANSLATE_ORIGIN (1 << 19)
void properties_register(wmOperatorType *ot, int flags);
/* `transform_orientations.cc` */
void calc_orientation_from_type(const bContext *C, float r_mat[3][3]);
/**
* \note The resulting matrix may not be orthogonal,
* callers that depend on `r_mat` to be orthogonal should use #orthogonalize_m3.
*
* A non orthogonal matrix may be returned when:
* - #V3D_ORIENT_GIMBAL the result won't be orthogonal unless the object has no rotation.
* - #V3D_ORIENT_LOCAL may contain shear from non-uniform scale in parent/child relationships.
* - #V3D_ORIENT_CUSTOM may have been created from #V3D_ORIENT_LOCAL.
*/
short calc_orientation_from_type_ex(const Main &bmain,
const Scene *scene,
ViewLayer *view_layer,
const View3D *v3d,
const RegionView3D *rv3d,
Object *ob,
Object *obedit,
short orientation_index,
int pivot_point,
float r_mat[3][3]);
bool calc_pivot_pos(const bContext *C, const short pivot_type, float r_pivot_pos[3]);
/* transform gizmos */
void VIEW3D_GGT_xform_gizmo(wmGizmoGroupType *gzgt);
/**
* Only poll, flag & gzmap_params differ.
*/
void VIEW3D_GGT_xform_gizmo_context(wmGizmoGroupType *gzgt);
void VIEW3D_GGT_xform_cage(wmGizmoGroupType *gzgt);
void VIEW3D_GGT_xform_shear(wmGizmoGroupType *gzgt);
/* `transform_gizmo_extrude_3d.cc` */
void VIEW3D_GGT_xform_extrude(wmGizmoGroupType *gzgt);
/* Generic 2D transform gizmo callback assignment. */
void ED_widgetgroup_gizmo2d_xform_callbacks_set(wmGizmoGroupType *gzgt);
void ED_widgetgroup_gizmo2d_xform_no_cage_callbacks_set(wmGizmoGroupType *gzgt);
void ED_widgetgroup_gizmo2d_resize_callbacks_set(wmGizmoGroupType *gzgt);
void ED_widgetgroup_gizmo2d_rotate_callbacks_set(wmGizmoGroupType *gzgt);
#define SNAP_INCREMENTAL_ANGLE DEG2RAD(5.0)
struct TransformBounds {
/** Center for transform widget. */
float center[3];
/** Bounding-box of selection for transform widget. */
float min[3], max[3];
/** Normalized axis. */
float axis[3][3];
float axis_min[3], axis_max[3];
/**
* When #TransformCalcParams.use_local_axis is used.
* This is the local space matrix the caller may need to access.
*/
bool use_matrix_space;
float matrix_space[4][4];
};
struct TransformCalcParams {
uint use_only_center : 1;
uint use_local_axis : 1;
/** Use #Scene::orientation_type when zero, otherwise subtract one and use. */
ushort orientation_index;
};
/**
* Centroid, bound-box, of selection.
*
* Returns total items selected.
*/
int calc_gizmo_stats(const bContext *C,
const TransformCalcParams *params,
TransformBounds *tbounds,
RegionView3D *rv3d);
/**
* Iterates over all the strips and finds the closest snapping candidate of either \a left_frame
* or \a right_frame, which might only be searched for on the given \a channel depending on snap
* settings. The closest snapping candidate will be the closest start or end frame of an existing
* strip.
* \returns True if there was anything to snap to.
*/
bool snap_sequencer_calc_drag_drop(Scene *scene,
ARegion *region,
const int left_frame,
const int right_frame,
const int channel,
int *r_snap_distance,
float2 *r_snap_point);
void snap_sequencer_draw_drag_drop(Scene *scene, ARegion *region, const float2 snap_point);
} // namespace ed::transform
} // namespace blender

View File

@@ -0,0 +1,229 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
#include "DNA_listBase.h"
#include "DNA_scene_types.h"
namespace blender {
// #define DEBUG_SNAP_TIME
struct BMEdge;
struct BMFace;
struct BMVert;
struct ARegion;
struct Depsgraph;
struct Object;
struct Scene;
struct View3D;
namespace ed::transform {
/* `transform_snap_object.cc` */
/* ED_transform_snap_object_*** API */
enum eSnapEditType {
SNAP_GEOM_FINAL = 0,
SNAP_GEOM_CAGE = 1,
SNAP_GEOM_EDIT = 2, /* Bmesh for mesh-type. */
};
enum eSnapOcclusionTest {
SNAP_OCCLUSION_NEVER = 0,
SNAP_OCCLUSION_AS_SEEM = 1,
SNAP_OCCLUSION_ALWAYS = 2,
};
/** used for storing multiple hits */
struct SnapObjectHitDepth {
SnapObjectHitDepth *next, *prev;
float depth;
float co[3];
/**
* Needed to tell which ray-cast this was part of,
* the same object may be part of many ray-casts when dupli's are used.
*/
unsigned int ob_uuid;
};
/** parameters that define which objects will be used to snap. */
struct SnapObjectParams {
/** Special context sensitive handling for the active or selected object. */
eSnapTargetOP snap_target_select;
/** Geometry for snapping in edit mode. */
eSnapEditType edit_mode_type;
/** Snap to or ignore the front-most object. */
eSnapOcclusionTest occlusion_test;
/** Grid unit size. "0.0" is automatic. */
float grid_size;
/** Break nearest face snapping into steps to improve transformations across U-shaped targets. */
short face_nearest_steps;
/** Exclude back facing geometry from snapping. */
bool use_backface_culling : 1;
/** Enable to force nearest face snapping to snap to target the source was initially near. */
bool keep_on_same_target : 1;
/**
* Allow snapping to include all objects even when a mesh is in edit mode.
*
* \note Use with care: multiple calls to the snap-context may crash.
* See #148788.
*/
bool ignore_editmode_filtering : 1;
};
struct SnapObjectContext;
SnapObjectContext *snap_object_context_create();
void snap_object_context_destroy(SnapObjectContext *sctx);
/** Callbacks to filter how snap works. */
void snap_object_context_set_editmesh_callbacks(SnapObjectContext *sctx,
bool (*test_vert_fn)(BMVert *, void *user_data),
bool (*test_edge_fn)(BMEdge *, void *user_data),
bool (*test_face_fn)(BMFace *, void *user_data),
void *user_data);
bool snap_object_project_ray_ex(SnapObjectContext *sctx,
Depsgraph *depsgraph,
const View3D *v3d,
const SnapObjectParams *params,
const float ray_start[3],
const float ray_normal[3],
float *ray_depth,
/* return args */
float r_loc[3],
float r_no[3],
int *r_index,
const Object **r_ob,
float r_obmat[4][4]);
/**
* Convenience function for snap ray-casting.
*
* Given a ray, cast it into the scene (snapping to faces).
*
* \return Snap success
*/
bool snap_object_project_ray(SnapObjectContext *sctx,
Depsgraph *depsgraph,
const View3D *v3d,
const SnapObjectParams *params,
const float ray_start[3],
const float ray_normal[3],
float *ray_depth,
float r_co[3],
float r_no[3]);
/**
* Fill in a list of all hits.
*
* \param ray_depth: Only depths in this range are considered, -1.0 for maximum.
* \param sort: Optionally sort the hits by depth.
* \param r_hit_list: List of #SnapObjectHitDepth (caller must free).
*/
bool snap_object_project_ray_all(SnapObjectContext *sctx,
Depsgraph *depsgraph,
const View3D *v3d,
const SnapObjectParams *params,
const float ray_start[3],
const float ray_normal[3],
float ray_depth,
bool sort,
ListBaseT<SnapObjectHitDepth> *r_hit_list);
/**
* Perform snapping.
*
* Given a 2D region value, snap to vert/edge/face/grid.
*
* \param sctx: Snap context.
* \param snap_to: Target elements to snap source to.
* \param params: Addition snapping options.
* \param init_co: Initial world-space coordinate of source (optional).
* \param mval: Current transformed screen-space coordinate or mouse position (optional).
* \param prev_co: Current transformed world-space coordinate of source (optional).
* \param dist_px: Maximum distance to snap (in pixels).
* \param r_loc: Snapped world-space coordinate.
* \param r_no: Snapped world-space normal (optional).
* \param r_index: Index of snapped-to target element (optional).
* \param r_ob: Snapped-to target object (optional).
* \param r_obmat: Matrix of snapped-to target object (optional).
* \param r_face_nor: World-space normal of snapped-to target face (optional).
* \return Snapped-to element, #eSnapMode.
*/
eSnapMode snap_object_project_view3d_ex(SnapObjectContext *sctx,
Depsgraph *depsgraph,
const ARegion *region,
const View3D *v3d,
const eSnapMode snap_to,
const SnapObjectParams *params,
const float init_co[3],
const float mval[2],
const float prev_co[3],
float *dist_px,
float r_loc[3],
float r_no[3],
int *r_index,
const Object **r_ob,
float r_obmat[4][4],
float r_face_nor[3]);
/**
* Convenience function for performing snapping.
*
* Given a 2D region value, snap to vert/edge/face.
*
* \param sctx: Snap context.
* \param snap_to: Target elements to snap source to.
* \param params: Addition snapping options.
* \param init_co: Initial world-space coordinate of source (optional).
* \param mval: Current transformed screen-space coordinate or mouse position (optional).
* \param prev_co: Current transformed world-space coordinate of source (optional).
* \param dist_px: Maximum distance to snap (in pixels).
* \param r_loc: Snapped world-space coordinate.
* \param r_no: Snapped world-space normal (optional).
* \return Snapped-to element, #eSnapMode.
*/
eSnapMode snap_object_project_view3d(SnapObjectContext *sctx,
Depsgraph *depsgraph,
const ARegion *region,
const View3D *v3d,
const eSnapMode snap_to,
const SnapObjectParams *params,
const float init_co[3],
const float mval[2],
const float prev_co[3],
float *dist_px,
/* return args */
float r_loc[3],
float r_no[3]);
/**
* see: #snap_object_project_ray_all
*/
bool object_project_all_view3d_ex(SnapObjectContext *sctx,
Depsgraph *depsgraph,
const ARegion *region,
const View3D *v3d,
const SnapObjectParams *params,
const float mval[2],
float ray_depth,
bool sort,
ListBaseT<SnapObjectHitDepth> *r_hit_list);
#ifdef DEBUG_SNAP_TIME
void ED_transform_snap_object_time_average_print();
#else
# define ED_transform_snap_object_time_average_print() void(0)
#endif
} // namespace ed::transform
} // namespace blender

View File

@@ -0,0 +1,69 @@
/* SPDX-FileCopyrightText: 2008 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
namespace blender {
struct Object;
struct bContext;
struct TransVert {
float *loc;
float oldloc[3], maploc[3];
float normal[3];
int flag;
};
struct TransVertStore {
TransVert *transverts;
int transverts_tot;
int mode;
};
/**
* \param obedit: When `mode` has the #TM_CALC_MAPLOC flag set, `obedit` must be evaluated,
* to access evaluated vertices.
*/
void ED_transverts_create_from_obedit(TransVertStore *tvs, const Object *obedit, int mode);
void ED_transverts_update_obedit(TransVertStore *tvs, Object *obedit);
void ED_transverts_free(TransVertStore *tvs);
bool ED_transverts_check_obedit(const Object *obedit);
bool ED_transverts_poll(bContext *C);
/* currently only used for bmesh index values */
enum {
/** Tag to make trans verts. */
TM_INDEX_ON = 1,
/** Don't make verts. */
TM_INDEX_OFF = 0,
/** Don't make verts (when the index values point to trans-verts). */
TM_INDEX_SKIP = -1,
};
/* mode flags: */
enum {
/** all joints (for bones only) */
TM_ALL_JOINTS = (1 << 0),
/** skip handles when control point is selected (for curves only) */
TM_SKIP_HANDLES = (1 << 1),
/** fill in normals when available */
TM_CALC_NORMALS = (1 << 2),
/** Calculates #TransVert.maploc where possible. */
TM_CALC_MAPLOC = (1 << 2),
};
enum {
/* SELECT == (1 << 0) */
/** Calculated when #TM_CALC_MAPLOC is set. */
TX_VERT_USE_MAPLOC = (1 << 1),
/** Calculated when #TM_CALC_NORMALS is set, avoid nonzero check. */
TX_VERT_USE_NORMAL = (1 << 2),
};
} // namespace blender

View File

@@ -0,0 +1,175 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
#include "BLI_sys_types.h"
#include "BLI_vector.hh"
struct CLG_LogRef;
namespace blender {
struct Base;
struct ID;
struct Main;
struct MemFile;
struct PointerRNA;
struct Object;
struct Scene;
struct UndoStack;
struct ViewLayer;
struct bContext;
struct wmOperator;
struct wmOperatorType;
struct wmWindowManager;
/* ed_undo.cc */
/**
* Run from the main event loop, basic checks that undo is left in a correct state.
*/
bool ED_undo_is_state_valid(bContext *C);
void ED_undo_group_begin(bContext *C);
void ED_undo_group_end(bContext *C);
void ED_undo_push(bContext *C, const char *str);
void ED_undo_push_op(bContext *C, wmOperator *op);
void ED_undo_grouped_push(bContext *C, const char *str);
void ED_undo_grouped_push_op(bContext *C, wmOperator *op);
void ED_undo_pop_op(bContext *C, wmOperator *op);
void ED_undo_pop(bContext *C);
void ED_undo_redo(bContext *C);
void ED_OT_undo(wmOperatorType *ot);
void ED_OT_undo_push(wmOperatorType *ot);
void ED_OT_redo(wmOperatorType *ot);
void ED_OT_undo_redo(wmOperatorType *ot);
void ED_OT_undo_history(wmOperatorType *ot);
/**
* UI callbacks should call this rather than calling WM_operator_repeat() themselves.
*
* \return true when repeat succeeded.
*/
bool ED_undo_operator_repeat(bContext *C, wmOperator *op);
/**
* Convenience since UI callbacks use this mostly.
*/
void ED_undo_operator_repeat_cb(bContext *C, void *arg_op, void *arg_unused);
void ED_undo_operator_repeat_cb_evt(bContext *C, void *arg_op, int arg_unused);
/**
* Name optionally, function used to check for operator redo panel.
*/
bool ED_undo_is_valid(const bContext *C, const char *undoname);
/**
* Returns true if there are redo steps available.
*/
bool ED_undo_has_redo_step(const bContext *C);
bool ED_undo_is_memfile_compatible(const bContext *C);
/* Unfortunate workaround for limits mixing undo systems. */
/**
* When a property of ID changes, return false.
*
* This is to avoid changes to a property making undo pushes
* which are ignored by the undo-system.
* For example, changing a brush property isn't stored by sculpt-mode undo steps.
* This workaround is needed until the limitation is removed, see: #61948.
*/
bool ED_undo_is_legacy_compatible_for_property(bContext *C, ID *id, PointerRNA &ptr);
/**
* This function addresses the problem of restoring undo steps when multiple windows are used.
* Since undo steps don't track the full context that created them it's possible an edit-mode
* undo step will attempt to restore edit-mode into a different window, scene or view-layer.
*
* Values `scene_p` & `view_layer_p` (typically initialized from the context)
* are updated from the visible windows using `scene_ref` as a reference.
* If the no window can be found, the values are left as-is.
*
* Since users may close windows before undoing, it's expected the window may be unavailable.
* When this happens the edit-mode objects wont be restored into edit-mode by
* #ED_undo_object_editmode_restore_helper which is acceptable since objects
* which aren't visible in any window don't need to enter edit-mode.
*/
void ED_undo_object_editmode_validate_scene_from_windows(wmWindowManager *wm,
const Scene *scene_ref,
Scene **scene_p,
ViewLayer **view_layer_p);
/**
* Load all our objects from `object_array` into edit-mode, clear everything else.
*/
void ED_undo_object_editmode_restore_helper(Scene *scene,
ViewLayer *view_layer,
Object **object_array,
uint object_array_len,
uint object_array_stride);
Vector<Object *> ED_undo_editmode_objects_from_view_layer(const Main &bmain,
const Scene *scene,
ViewLayer *view_layer);
Vector<Base *> ED_undo_editmode_bases_from_view_layer(const Main &bmain,
const Scene *scene,
ViewLayer *view_layer);
/**
* Ideally we won't access the stack directly,
* this is needed for modes which handle undo themselves (bypassing #ED_undo_push).
*
* Using global isn't great, this just avoids doing inline,
* causing `BKE_global.hh` & `BKE_main.hh` includes.
*/
UndoStack *ED_undo_stack_get();
/* Helpers. */
void ED_undo_object_set_active_or_warn(const Main &bmain,
Scene *scene,
ViewLayer *view_layer,
Object *ob,
const char *info,
CLG_LogRef *log);
/* `undo_system_types.cc` */
void ED_undosys_type_init();
void ED_undosys_type_free();
/* `memfile_undo.cc` */
bool ED_undosys_autosave_compatible(UndoStack *ustack);
/**
* If the last undo step is a memfile one, find the first #MemFileChunk matching given ID
* (using its session UUID), and tag it as "changed in the future".
*
* Since non-memfile undo-steps cannot automatically set this flag in the previous step as done
* with memfile ones, this has to be called manually by relevant undo code.
*
* \note Only current known case for this is undoing a switch from Object to Sculpt mode (see
* #82388).
*
* \note Calling this ID by ID is not optimal, as it will loop over all #MemFile.chunks until it
* finds the expected one. If this becomes an issue we'll have to add a mapping from session UUID
* to first #MemFileChunk in #MemFile itself
* (currently we only do that in #MemFileWriteData when writing a new step).
*/
void ED_undosys_stack_memfile_id_changed_tag(UndoStack *ustack, ID *id);
/**
* Get the total memory usage of all undo steps in the current undo stack.
*
* This function iterates through all undo steps and calculates their memory consumption.
* For sculpt undo steps, it uses the specialized sculpt memory calculation function.
* For other undo step types, it uses the generic `data_size` field.
*
* \return Total memory usage in bytes, or 0 if no undo stack is available.
*/
size_t ED_undosys_total_memory_calc(UndoStack *ustack);
} // namespace blender

View File

@@ -0,0 +1,26 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
#include "BLI_vector.hh"
namespace blender {
/* Structs */
struct SpaceUserPref;
void ED_operatortypes_userpref();
Vector<int> ED_userpref_tabs_list(SpaceUserPref *prefs);
bool ED_userpref_tab_has_search_result(SpaceUserPref *sprefs, int index);
void ED_userpref_search_string_set(SpaceUserPref *sprefs, const char *value);
int ED_userpref_search_string_length(SpaceUserPref *sprefs);
const char *ED_userpref_search_string_get(SpaceUserPref *sprefs);
} // namespace blender

View File

@@ -0,0 +1,174 @@
/* SPDX-FileCopyrightText: 2008 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
#include "WM_types.hh"
namespace blender {
struct Main;
struct bContext;
class WorkspaceStatus;
namespace bke::id {
class IDRemapper;
}
/* `ed_util.cc` */
void ED_editors_init_for_undo(Main *bmain);
void ED_editors_init(bContext *C);
/**
* Frees all edit-mode stuff.
*/
void ED_editors_exit(Main *bmain, bool do_undo_system);
bool ED_editors_flush_edits_for_object_ex(Main *bmain,
Object *ob,
bool for_render,
bool check_needs_flush);
bool ED_editors_flush_edits_for_object(Main *bmain, Object *ob);
/**
* Flush any temp data from object editing to DNA before writing files, rendering, copying, etc.
*/
bool ED_editors_flush_edits_ex(Main *bmain, bool for_render, bool check_needs_flush);
bool ED_editors_flush_edits(Main *bmain);
/**
* Use to free ID references within runtime data (stored outside of DNA)
*
* \param new_id: may be NULL to unlink \a old_id.
*/
void ED_spacedata_id_remap_single(ScrArea *area, SpaceLink *sl, ID *old_id, ID *new_id);
void ED_spacedata_id_remap(ScrArea *area, SpaceLink *sl, const bke::id::IDRemapper &mappings);
/**
* Helper for context sensitive operations: Returns the "id" context member wrapped in a
* #PointerRNA vector. Useful when the API uses vectors to also support acting on multiple IDs,
* e.g. as returned by #ED_operator_get_ids_from_context_as_vec().
*/
Vector<PointerRNA> ED_operator_single_id_from_context_as_vec(const bContext *C);
/**
* Helper for context sensitive operations: Returns the "selected_ids" context member or, if none,
* the "id" context member as a #PointerRNA vector. Batch operations can use this to get all IDs to
* act on, including a fallback to the active ID if there's no selection.
*/
Vector<PointerRNA> ED_operator_get_ids_from_context_as_vec(const bContext *C);
void ED_operatortypes_edutils();
/* Drawing */
/**
* Callback that draws a line between the mouse and a position given as the initial argument.
*/
void ED_region_draw_mouse_line_cb(const bContext *C, ARegion *region, void *arg_info);
/**
* \note Keep in sync with #BKE_image_stamp_buf.
*/
void ED_region_image_metadata_draw(
int x, int y, const ImBuf *ibuf, const rctf *frame, float zoomx, float zoomy);
void ED_region_image_overlay_info_text_draw(const int render_size_x,
const int render_size_y,
const int viewer_size_x,
const int viewer_size_y,
const int draw_offset_x,
const int draw_offset_y);
void ED_region_render_region_draw(
int x, int y, const rcti *frame, float zoomx, float zoomy, float passepartout_alpha);
/* Slider */
struct tSlider;
enum SliderMode { SLIDER_MODE_PERCENT = 0, SLIDER_MODE_FLOAT = 1 };
tSlider *ED_slider_create(bContext *C);
/**
* For modal operations so the percentage doesn't pop on the first mouse movement.
*/
void ED_slider_init(tSlider *slider, const wmEvent *event);
/**
* Calculate slider factor based on mouse position.
*/
bool ED_slider_modal(tSlider *slider, const wmEvent *event);
void ED_slider_destroy(bContext *C, tSlider *slider);
/**
* Return string based on the current state of the slider.
*/
void ED_slider_status_string_get(const tSlider *slider,
char *status_string,
size_t size_of_status_string);
void ED_slider_status_get(const tSlider *slider, WorkspaceStatus &status);
float ED_slider_factor_get(const tSlider *slider);
void ED_slider_factor_set(tSlider *slider, float factor);
/**
* By default the increment step is 0.1, which depending on the factor bounds might not be desired.
* Only has an effect if increment is allowed and enabled.
* See #ED_slider_allow_increments_set.
* \param increment_step: cannot be 0.
*/
void ED_slider_increment_step_set(tSlider *slider, float increment_step);
/** One bool value for each side of the slider. Allows to enable overshoot only on one side. */
void ED_slider_allow_overshoot_set(tSlider *slider, bool lower, bool upper);
/**
* Set the soft limits for the slider, which are applied until the user enables overshooting.
*/
void ED_slider_factor_bounds_set(tSlider *slider,
float factor_bound_lower,
float factor_bound_upper);
bool ED_slider_allow_increments_get(const tSlider *slider);
void ED_slider_allow_increments_set(tSlider *slider, bool value);
void ED_slider_mode_set(tSlider *slider, SliderMode mode);
SliderMode ED_slider_mode_get(const tSlider *slider);
void ED_slider_unit_set(tSlider *slider, const char *unit);
/* Set a name that will show next to the slider to indicate which property is modified currently.
* To clear, set to an empty string. */
void ED_slider_property_label_set(tSlider *slider, const char *property_label);
/* Composition Guides */
enum eCompositionGuideFlags : short;
void ED_draw_composition_guides(uint shdr_pos,
eCompositionGuideFlags flag,
const rctf *rect,
const float color[4]);
/* ************** XXX OLD CRUFT WARNING ************* */
/**
* Now only used in 2D spaces, like time, f-curve, NLA, image, etc.
*
* \note Shift/Control are not configurable key-bindings.
*/
void apply_keyb_grid(
bool shift, bool ctrl, float *val, float fac1, float fac2, float fac3, int invert);
/* where else to go ? */
void unpack_menu(bContext *C,
const char *opname,
const char *id_name,
const char *abs_name,
const char *folder,
PackedFile *pf);
} // namespace blender

View File

@@ -0,0 +1,27 @@
/* SPDX-FileCopyrightText: 2008 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
namespace blender {
struct ARegion;
struct bContext;
struct wmEvent;
struct wmOperator;
/* `ed_util_imbuf.cc` */
void ED_imbuf_sample_draw(const bContext *C, ARegion *region, void *arg_info);
void ED_imbuf_sample_exit(bContext *C, wmOperator *op);
wmOperatorStatus ED_imbuf_sample_invoke(bContext *C, wmOperator *op, const wmEvent *event);
wmOperatorStatus ED_imbuf_sample_modal(bContext *C, wmOperator *op, const wmEvent *event);
void ED_imbuf_sample_cancel(bContext *C, wmOperator *op);
bool ED_imbuf_sample_poll(bContext *C);
} // namespace blender

View File

@@ -0,0 +1,398 @@
/* SPDX-FileCopyrightText: 2008 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
#include "DNA_listBase.h"
#include "BLI_function_ref.hh"
#include "BLI_vector_list.hh"
#include "BKE_customdata.hh"
namespace blender {
struct ARegion;
struct ARegionType;
struct BMEdge;
struct BMEditMesh;
struct BMFace;
struct BMLoop;
struct BMVert;
struct BMesh;
struct Image;
struct ImageUser;
struct Main;
struct Object;
struct Scene;
struct SpaceImage;
struct ToolSettings;
struct View2D;
struct ViewLayer;
struct bContext;
struct bNode;
struct bNodeTree;
struct wmKeyConfig;
struct wmTimer;
/* `uvedit_ops.cc` */
void ED_operatortypes_uvedit();
void ED_operatormacros_uvedit();
void ED_keymap_uvedit(wmKeyConfig *keyconf);
/**
* Be careful when using this, it bypasses all synchronization options.
*/
void ED_uvedit_select_all(const ToolSettings *ts, BMesh *bm);
void ED_uvedit_foreach_uv(const Scene *scene,
BMesh *bm,
const bool skip_invisible,
const bool selected,
FunctionRef<void(float[2])> user_fn);
void ED_uvedit_foreach_uv_multi(const Scene *scene,
Span<Object *> objects_edit,
const bool skip_invisible,
const bool skip_nonselected,
FunctionRef<void(float[2])> user_fn);
bool ED_uvedit_minmax_multi(const Scene *scene,
Span<Object *> objects_edit,
float r_min[2],
float r_max[2]);
bool ED_uvedit_center_multi(const Scene *scene,
Span<Object *> objects_edit,
float r_cent[2],
char mode);
bool ED_uvedit_center_from_pivot_ex(const Main &bmain,
const SpaceImage *sima,
Scene *scene,
ViewLayer *view_layer,
float r_center[2],
char mode,
bool *r_has_select);
bool ED_object_get_active_image(Object *ob,
int mat_nr,
Image **r_ima,
ImageUser **r_iuser,
const bNode **r_node,
const bNodeTree **r_ntree);
void ED_object_assign_active_image(Main *bmain, Object *ob, int mat_nr, Image *ima);
bool ED_uvedit_test(Object *obedit);
/* `uvedit_select.cc` */
namespace ed::uv {
/**
* Abstract away the details of syncing selection from the mesh (viewport)
* to a UV state which is "synchronized".
*
* Where practical (see note below) this is a preferred alternative to clearing the
* UV selection state and re-initializing it from the mesh, because there may be UV's
* selected on one UV island and not another, even though the vertices are shared.
* Flushing and re-initializing will set both, losing the users selection.
*
* Note that what is considered practical is open to interpretation,
* picking individual elements and basic selection actions should be supported.
* Selection actions such as random or by vertex group... isn't so practical.
*/
class UVSyncSelectFromMesh : NonCopyable {
private:
char uv_sticky_;
BMesh &bm_;
VectorList<BMVert *> bm_verts_select_;
VectorList<BMEdge *> bm_edges_select_;
VectorList<BMFace *> bm_faces_select_;
VectorList<BMVert *> bm_verts_deselect_;
VectorList<BMEdge *> bm_edges_deselect_;
VectorList<BMFace *> bm_faces_deselect_;
public:
UVSyncSelectFromMesh(BMesh &bm, char uv_sticky) : uv_sticky_(uv_sticky), bm_(bm) {}
UVSyncSelectFromMesh(const UVSyncSelectFromMesh &) = delete;
static std::unique_ptr<UVSyncSelectFromMesh> create_if_needed(const ToolSettings &ts, BMesh &bm);
void apply();
/* Select. */
void vert_select_enable(BMVert *v);
void edge_select_enable(BMEdge *f);
void face_select_enable(BMFace *f);
/* De-Select. */
void vert_select_disable(BMVert *v);
void edge_select_disable(BMEdge *f);
void face_select_disable(BMFace *f);
/* Select set. */
void vert_select_set(BMVert *v, bool value);
void edge_select_set(BMEdge *f, bool value);
void face_select_set(BMFace *f, bool value);
};
} // namespace ed::uv
bool ED_uvedit_sync_uvselect_ignore(const ToolSettings *ts);
bool ED_uvedit_sync_uvselect_is_valid_or_ignore(const ToolSettings *ts, const BMesh *bm);
void ED_uvedit_sync_uvselect_ensure_if_needed(const ToolSettings *ts, BMesh *bm);
/* Visibility and selection tests. */
bool uvedit_face_visible_test_ex(const ToolSettings *ts, const BMFace *efa);
bool uvedit_face_select_test_ex(const ToolSettings *ts, const BMesh *bm, const BMFace *efa);
bool uvedit_edge_select_test_ex(const ToolSettings *ts,
const BMesh *bm,
const BMLoop *l,
const BMUVOffsets &offsets);
bool uvedit_uv_select_test_ex(const ToolSettings *ts,
const BMesh *bm,
const BMLoop *l,
const BMUVOffsets &offsets);
bool uvedit_face_visible_test(const Scene *scene, const BMFace *efa);
bool uvedit_face_select_test(const Scene *scene, const BMesh *bm, const BMFace *efa);
bool uvedit_edge_select_test(const Scene *scene,
const BMesh *bm,
const BMLoop *l,
const BMUVOffsets &offsets);
bool uvedit_uv_select_test(const Scene *scene,
const BMesh *bm,
const BMLoop *l,
const BMUVOffsets &offsets);
/* Low level loop selection, this ignores the selection modes. */
bool uvedit_loop_vert_select_get(const ToolSettings *ts, const BMesh *bm, const BMLoop *l);
bool uvedit_loop_edge_select_get(const ToolSettings *ts, const BMesh *bm, const BMLoop *l);
void uvedit_loop_vert_select_set(const ToolSettings *ts,
const BMesh *bm,
BMLoop *l,
const bool select);
void uvedit_loop_edge_select_set(const ToolSettings *ts,
const BMesh *bm,
BMLoop *l,
const bool select);
/* Individual UV element selection functions. */
/**
* \brief Select UV Face
*
* Changes selection state of a single UV Face.
*/
void uvedit_face_select_set(const Scene *scene, BMesh *bm, BMFace *efa, bool select);
/**
* \brief Select UV Edge
*
* Changes selection state of a single UV Edge.
*/
void uvedit_edge_select_set(const Scene *scene, BMesh *bm, BMLoop *l, bool select);
/**
* \brief Select UV Vertex
*
* Changes selection state of a single UV vertex.
*/
void uvedit_uv_select_set(const Scene *scene, BMesh *bm, BMLoop *l, bool select);
/* Low level functions for (de)selecting individual UV elements. Ensure UV face visibility before
* use. */
void uvedit_face_select_enable(const Scene *scene, BMesh *bm, BMFace *efa);
void uvedit_face_select_disable(const Scene *scene, BMesh *bm, BMFace *efa);
void uvedit_edge_select_enable(const Scene *scene, BMesh *bm, BMLoop *l);
void uvedit_edge_select_disable(const Scene *scene, BMesh *bm, BMLoop *l);
void uvedit_uv_select_enable(const Scene *scene, BMesh *bm, BMLoop *l);
void uvedit_uv_select_disable(const Scene *scene, BMesh *bm, BMLoop *l);
/* Sticky mode UV element selection functions. */
void uvedit_face_select_set_with_sticky(
const Scene *scene, BMesh *bm, BMFace *efa, bool select, const BMUVOffsets &offsets);
void uvedit_edge_select_set_with_sticky(
const Scene *scene, BMesh *bm, BMLoop *l, bool select, const BMUVOffsets &offsets);
void uvedit_uv_select_set_with_sticky(
const Scene *scene, BMesh *bm, BMLoop *l, bool select, const BMUVOffsets &offsets);
/* Low level functions for sticky element selection (sticky mode independent). Type of sticky
* selection is specified explicitly (using sticky_flag, except for face selection). */
void uvedit_face_select_shared_vert(
const Scene *scene, BMesh *bm, BMFace *efa, const bool select, const BMUVOffsets &offsets);
/**
* Selects UV edges and shared vertices according to sticky_flag.
*
* \param sticky_flag:
* - #UV_STICKY_LOCATION: selects all UV edges that share the same mesh vertices and UV coords.
* - #UV_STICKY_VERT: selects all UV edges sharing the same mesh vertices.
*/
void uvedit_edge_select_shared_vert(const Scene *scene,
BMesh *bm,
BMLoop *l,
const bool select,
const int sticky_flag,
const BMUVOffsets &offsets);
/**
* Selects shared UVs based on #sticky_flag.
*
* \param sticky_flag: Type of sticky selection:
* - #UV_STICKY_LOCATION: selects all UVs sharing same mesh vertex and UV coords.
* - #UV_STICKY_VERT: selects all UVs sharing same mesh vertex.
*/
void uvedit_uv_select_shared_vert(const Scene *scene,
BMesh *bm,
BMLoop *l,
const bool select,
const int sticky_flag,
const BMUVOffsets &offsets);
/**
* Sets required UV edge flags as specified by the `sticky_flag`.
*/
void uvedit_edge_select_set_noflush(const Scene *scene,
BMesh *bm,
BMLoop *l,
const bool select,
const int sticky_flag,
const BMUVOffsets &offsets);
/**
* \brief UV Select Mode set
*
* Updates selection state for UVs based on the select mode and sticky mode. Similar to
* #EDBM_selectmode_set.
*/
void ED_uvedit_selectmode_clean(const Scene *scene, Object *obedit);
void ED_uvedit_selectmode_clean_multi(bContext *C);
void ED_uvedit_select_sync_multi(bContext *C);
void ED_uvedit_sticky_selectmode_update(bContext *C);
/**
* \brief UV Select Mode Flush
*
* Flushes selections upwards as dictated by the UV select mode.
*/
void ED_uvedit_selectmode_flush(const Scene *scene, BMesh *bm);
/**
* Mode independent UV selection/de-selection flush from vertices.
*
* \param select: When true, flush the selection state to de-selected elements,
* otherwise perform the opposite, flushing de-selection.
*/
void uvedit_select_flush_from_verts(const Scene *scene, BMesh *bm, bool select);
bool ED_uvedit_nearest_uv_multi(const View2D *v2d,
const Scene *scene,
Span<Object *> objects,
const float mval_fl[2],
const bool ignore_selected,
float *dist_sq,
float r_uv[2]);
BMFace **ED_uvedit_selected_faces(const Scene *scene, BMesh *bm, int len_max, int *r_faces_len);
BMLoop **ED_uvedit_selected_edges(const Scene *scene, BMesh *bm, int len_max, int *r_edges_len);
BMLoop **ED_uvedit_selected_verts(const Scene *scene, BMesh *bm, int len_max, int *r_verts_len);
void ED_uvedit_active_vert_loop_set(BMesh *bm, BMLoop *l);
BMLoop *ED_uvedit_active_vert_loop_get(const ToolSettings *ts, BMesh *bm);
void ED_uvedit_active_edge_loop_set(BMesh *bm, BMLoop *l);
BMLoop *ED_uvedit_active_edge_loop_get(const ToolSettings *ts, BMesh *bm);
/**
* Intentionally don't return #UV_SELECT_ISLAND as it's not an element type.
* In this case return #UV_SELECT_VERT as a fallback.
*/
char ED_uvedit_select_mode_get(const Scene *scene);
bool ED_uvedit_select_island_check(const ToolSettings *ts);
void ED_uvedit_select_sync_flush(const ToolSettings *ts, BMesh *bm, bool select);
/* `uvedit_unwrap_ops.cc` */
void ED_uvedit_deselect_all(const Scene *scene, Object *obedit, int action);
void ED_uvedit_get_aspect(Object *obedit, float *r_aspx, float *r_aspy);
/**
* Return the X / Y aspect (wider aspects are over 1, taller are below 1).
* Apply this aspect by multiplying with the Y axis (X aspect is always 1 & unchanged).
*/
float ED_uvedit_get_aspect_y(Object *obedit);
void ED_uvedit_get_aspect_from_material(Object *ob,
const int material_index,
float *r_aspx,
float *r_aspy);
/** Return true if the timer is managed by live-unwrap. */
bool ED_uvedit_live_unwrap_timer_check(const wmTimer *timer);
/**
* \param win_modal: Support interactive (modal) unwrapping that updates with a timer.
*/
void ED_uvedit_live_unwrap_begin(Scene *scene, Object *obedit, struct wmWindow *win_modal);
void ED_uvedit_live_unwrap_re_solve();
void ED_uvedit_live_unwrap_end(bool cancel);
void ED_uvedit_live_unwrap(const Scene *scene, Span<Object *> objects);
void ED_uvedit_add_simple_uvs(Main *bmain, const Scene *scene, Object *ob);
/* `uvedit_draw.cc` */
void ED_image_draw_cursor(ARegion *region, const float cursor[2]);
/* `uvedit_buttons.cc` */
void ED_uvedit_buttons_register(ARegionType *art);
/* `uvedit_islands.cc` */
struct FaceIsland {
FaceIsland *next;
FaceIsland *prev;
BMFace **faces;
int faces_len;
/**
* \note While this is duplicate information,
* it allows islands from multiple meshes to be stored in the same list.
*/
BMUVOffsets offsets;
float aspect_y;
};
/**
* Calculate islands and add them to \a island_list returning the number of items added.
*/
int bm_mesh_calc_uv_islands(const Scene *scene,
BMesh *bm,
ListBaseT<FaceIsland> *island_list,
const bool only_selected_faces,
const bool only_selected_uvs,
const bool use_seams,
const float aspect_y,
const BMUVOffsets &offsets);
/**
* Returns true if UV coordinates lie on a valid tile in UDIM grid or tiled image.
*/
bool uv_coords_isect_udim(const Image *image, const int udim_grid[2], const float coords[2]);
} // namespace blender

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,134 @@
/* SPDX-FileCopyrightText: 2008 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editors
*/
#pragma once
#include "DNA_object_enums.h"
#include "DNA_view3d_types.h"
#include "IMB_imbuf_types.hh"
namespace blender {
/* ********* exports for space_view3d/ module for offscreen rendering ********** */
struct ARegion;
struct bContext;
struct Depsgraph;
struct GPUOffScreen;
struct GPUViewport;
struct Scene;
struct View3D;
struct View3DShading;
void ED_view3d_draw_offscreen(Depsgraph *depsgraph,
const Scene *scene,
eDrawType drawtype,
View3D *v3d,
ARegion *region,
bContext *context,
int winx,
int winy,
const float viewmat[4][4],
const float winmat[4][4],
bool is_image_render,
bool draw_background,
const char *viewname,
bool do_color_management,
bool restore_rv3d_mats,
GPUOffScreen *ofs,
GPUViewport *viewport);
/**
* Creates separate fake 3d views (wrapping #ED_view3d_draw_offscreen). Similar too
* #ED_view_draw_offscreen_imbuf_simple, but takes view/projection matrices as arguments.
*/
void ED_view3d_draw_offscreen_simple(Depsgraph *depsgraph,
Scene *scene,
View3DShading *shading_override,
bContext *context,
eDrawType drawtype,
int object_type_exclude_viewport_override,
int object_type_exclude_select_override,
int winx,
int winy,
unsigned int draw_flags,
const float viewmat[4][4],
const float winmat[4][4],
float clip_start,
float clip_end,
float xr_vignette_aperture,
bool is_xr_surface,
bool is_image_render,
bool draw_background,
const char *viewname,
bool do_color_management,
Object *camera_override,
GPUOffScreen *ofs,
GPUViewport *viewport);
/**
* Utility func for ED_view3d_draw_offscreen
*
* \param ofs: Optional off-screen buffer, can be NULL.
* (avoids re-creating when doing multiple GL renders).
* \param viewport: Optional viewport data, can be NULL.
* (avoids re-creating when doing multiple GL renders,
* allows keeping track of state across frames).
* \param use_camera_view_bounds: if true and the viewport is looking through a camera, only render
* what the camera can see. In case the aspect ratio of the given `sizex` and `sizey` does not
* match the render aspect ratio of the scene, the returned image will be expanded so the camera
* view bounds are contained within it.
*/
ImBuf *ED_view3d_draw_offscreen_imbuf(Depsgraph *depsgraph,
Scene *scene,
eDrawType drawtype,
View3D *v3d,
ARegion *region,
int sizex,
int sizey,
ImBufFlags imbuf_flag,
int alpha_mode,
const char *viewname,
bool restore_rv3d_mats,
GPUOffScreen *ofs,
GPUViewport *viewport,
bool use_camera_view_bounds,
char err_out[256]);
/**
* Creates separate fake 3d views (wrapping #ED_view3d_draw_offscreen_imbuf)
*
* \param ofs: Optional off-screen buffer can be NULL.
* (avoids re-creating when doing multiple GL renders).
* \param viewport: Optional viewport data, can be NULL.
* (avoids re-creating when doing multiple GL renders,
* allows keeping track of state across frames).
*
* \note used by the sequencer
*/
ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Depsgraph *depsgraph,
Scene *scene,
View3DShading *shading_override,
eDrawType drawtype,
Object *camera,
int width,
int height,
ImBufFlags imbuf_flags,
eV3DOffscreenDrawFlag draw_flags,
int alpha_mode,
const char *viewname,
GPUOffScreen *ofs,
GPUViewport *viewport,
char err_out[256]);
/**
* Drawing off-screen is not supported while drawing,
* this is a simple check to use when the code path may occur within a draw call
* (Python scripting for example).
*/
bool ED_view3d_draw_offscreen_check_nested();
} // namespace blender

View File

@@ -0,0 +1,108 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#include <optional>
#include "BLI_compute_context.hh"
#include "BLI_string_ref.hh"
#include "BLI_vector.hh"
#include "BKE_compute_context_cache_fwd.hh"
#include "DNA_viewer_path_types.h"
namespace blender {
struct Main;
struct SpaceNode;
struct bNode;
struct bContext;
struct Object;
namespace ed::viewer_path {
/**
* Activates the given node in the context provided by the editor. This indirectly updates all
* non-pinned viewer paths in other editors (spreadsheet and 3d view).
*/
void activate_geometry_node(Main &bmain,
SpaceNode &snode,
bNode &node,
std::optional<int> item_identifier = std::nullopt);
/**
* Returns the object referenced by the viewer path. This only returns something if the viewer path
* *only* contains the object and nothing more.
*/
Object *parse_object_only(const ViewerPath &viewer_path);
/**
* Represents a parsed #ViewerPath for easier consumption.
*/
struct ViewerPathForGeometryNodesViewer {
Object *object;
/** #ModifierData.persistent_uid. */
int modifier_uid;
/** Contains only group node and simulation zone elements. */
Vector<const ViewerPathElem *> node_path;
int32_t viewer_node_id;
};
/**
* Parses a #ViewerPath into a #ViewerPathForGeometryNodesViewer or returns none if that does not
* work.
*/
std::optional<ViewerPathForGeometryNodesViewer> parse_geometry_nodes_viewer(
const ViewerPath &viewer_path);
/**
* Finds the node referenced by the #ViewerPath within the provided editor. If no node is
* referenced, null is returned. When two different editors show the same node group but in a
* different context, it's possible that the same node is active in one editor but not the other.
*/
bNode *find_geometry_nodes_viewer(const ViewerPath &viewer_path, SpaceNode &snode);
/**
* Checks if the node referenced by the viewer path and its entire context still exists. The node
* does not have to be visible for this to return true.
*/
bool exists_geometry_nodes_viewer(const ViewerPathForGeometryNodesViewer &parsed_viewer_path);
enum class UpdateActiveGeometryNodesViewerResult {
StillActive,
Updated,
NotActive,
};
/**
* Checks if the node referenced by the viewer and its entire context is still active, i.e. some
* editor is showing it. If not, the viewer path might be updated in minor ways (like changing the
* repeat zone iteration).
*/
UpdateActiveGeometryNodesViewerResult update_active_geometry_nodes_viewer(const bContext &C,
ViewerPath &viewer_path);
/**
* Some viewer path elements correspond to compute-contexts. This function converts from the viewer
* path element to the corresponding compute context if possible.
*
* \return The corresponding compute context or null.
*/
[[nodiscard]] const ComputeContext *compute_context_for_viewer_path_elem(
const ViewerPathElem &elem,
bke::ComputeContextCache &compute_context_cache,
const ComputeContext *parent_compute_context);
/**
* The inverse of #compute_context_for_viewer_path_elem. It helps to create a viewer path (which
* can be stored in .blend files) from a compute context.
*/
[[nodiscard]] ViewerPathElem *viewer_path_elem_for_compute_context(
const ComputeContext &compute_context);
} // namespace ed::viewer_path
} // namespace blender

View File

@@ -0,0 +1,469 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editorui
*
* Base class for all views (UIs to display data sets) and view items, supporting common features.
* https://developer.blender.org/docs/features/interface/views/
*
* One of the most important responsibilities of the base class is managing reconstruction,
* enabling state that is persistent over reconstructions/redraws. Other features:
* - Renaming
* - Custom context menus
* - Notifier listening
* - Drag controllers (dragging view items)
* - Drop targets (dropping onto/into view items)
*/
#pragma once
#include <array>
#include <memory>
#include <optional>
#include <string>
#include "DNA_defs.h"
#include "DNA_vec_types.h"
#include "BLI_span.hh"
#include "BLI_string_ref.hh"
#include "UI_interface.hh"
#include "UI_interface_layout.hh"
#include "WM_types.hh"
namespace blender {
struct bContext;
struct wmNotifier;
namespace ui {
struct ViewLink;
struct ButtonViewItem;
class AbstractViewItem;
class AbstractViewItemDragController;
enum class ViewScrollDirection {
UP,
DOWN,
};
struct Layout;
class AbstractView {
friend class AbstractViewItem;
friend struct ViewLink;
bool is_reconstructed_ = false;
/**
* Only one item can be renamed at a time. So rather than giving each item its own rename buffer
* (which just adds unused memory in most cases), have one here that is managed by the view.
*
* This fixed-size buffer is needed because that's what the rename button requires. In future we
* may be able to bind the button to a `std::string` or similar.
*/
std::unique_ptr<std::array<char, MAX_NAME>> rename_buffer_;
/* Search/filter string from the previous redraw, stored to detect changes. */
std::string prev_filter_string_;
bool needs_filtering_ = true;
/* See #get_bounds(). */
std::optional<rcti> bounds_;
std::string context_menu_title;
/** See #set_popup_keep_open(). */
bool popup_keep_open_ = false;
bool is_multiselect_supported_ = false;
public:
virtual ~AbstractView() = default;
/**
* If a view wants to support dropping data into it, it has to return a drop target here.
* That is an object implementing #DropTargetInterface.
*
* \note This drop target may be requested for each event. The view doesn't keep the drop target
* around currently. So it cannot contain persistent state.
*/
virtual std::unique_ptr<DropTargetInterface> create_drop_target();
/** Listen to a notifier, returning true if a redraw is needed. */
virtual bool listen(const wmNotifier &) const;
/**
* Enable filtering. Typically used to enable a filter text button. Triggered on Ctrl+F by
* default.
* \return True when filtering was enabled successfully.
*/
virtual bool begin_filtering(const bContext &C) const;
virtual void draw_overlays(const ARegion &region, const Block &block) const;
virtual void foreach_view_item(FunctionRef<void(AbstractViewItem &)> iter_fn) const = 0;
virtual bool supports_scrolling() const;
/**
* \return True when everything in this view is visible, i.e. no scrolling is needed.
*/
virtual bool is_fully_visible() const;
virtual void scroll(ViewScrollDirection direction);
/**
* From the current view state, return certain state that will be written to files (stored in
* #ARegion.view_states) to preserve it over UI changes and file loading. The state can be
* restored using #persistent_state_apply().
*
* Return an empty value if there's no state to preserve (default implementation).
*/
virtual std::optional<uiViewState> persistent_state() const;
/**
* Restore a view state given in \a state, which was created by #persistent_state() for saving in
* files, and potentially loaded from a file.
*/
virtual void persistent_state_apply(const uiViewState &state);
/**
* Makes \a item valid for display in this view. Behavior is undefined for items not registered
* with this.
*/
void register_item(AbstractViewItem &item);
/** Only one item can be renamed at a time. */
bool is_renaming() const;
/** \return If renaming was started successfully. */
bool begin_renaming();
void end_renaming();
Span<char> get_rename_buffer() const;
MutableSpan<char> get_rename_buffer();
/**
* Get the rectangle containing all the view items that are in the layout, in button space.
* Updated as part of #block_end(), before that it's unset.
*/
std::optional<rcti> get_bounds() const;
std::string get_context_menu_title() const;
void set_context_menu_title(const std::string &title);
bool get_popup_keep_open() const;
/** If this view is displayed in a popup, don't close it when clicking to activate items. */
void set_popup_keep_open();
void clear_search_highlight();
void allow_multiselect_items();
bool is_multiselect_supported() const;
virtual AbstractViewItem *find_active_or_visible_item() const = 0;
virtual AbstractViewItem *navigate_left(AbstractViewItem *from) = 0;
virtual AbstractViewItem *navigate_right(AbstractViewItem *from) = 0;
virtual AbstractViewItem *navigate_up(AbstractViewItem *from) = 0;
virtual AbstractViewItem *navigate_down(AbstractViewItem *from) = 0;
virtual void scroll_active_into_view(bContext *C, bool scroll_active_to_center = false) = 0;
protected:
AbstractView() = default;
/**
* Items may want to do additional work when state changes. But these state changes can only be
* reliably detected after the view has completed reconstruction (see #is_reconstructed()). So
* the actual state changes are done in a delayed manner through this function.
*
* Overrides should call the base class implementation.
*/
virtual void change_state_delayed();
virtual void update_children_from_old(const AbstractView &old_view) = 0;
/**
* Match the view and its items against an earlier version of itself (if any) and copy the old UI
* state (e.g. collapsed, active, selected, renaming, etc.) to the new one. See
* #AbstractViewItem.update_from_old().
* After this, reconstruction is complete (see #is_reconstructed()).
*/
void update_from_old(Block &new_block);
/**
* Check if the view is fully (re-)constructed. That means, both the build function and
* #update_from_old() have finished.
*/
bool is_reconstructed() const;
void filter(std::optional<StringRef> filter_str);
const AbstractViewItem *search_highlight_item() const;
};
class AbstractViewItem {
friend class AbstractView;
friend class ViewItemAPIWrapper;
protected:
/**
* The view this item is a part of, and was registered for using #AbstractView::register_item().
* If this wasn't done, the behavior of items is undefined.
*/
AbstractView *view_ = nullptr;
/** See #view_item_button() */
ui::ButtonViewItem *view_item_but_ = nullptr;
bool is_activatable_ = true;
bool is_interactive_ = true;
/** See #is_hovered(). */
bool is_hovered_ = false;
bool is_active_ = false;
/** Only change using #set_selected() so overrides can sync changes to data. */
bool is_selected_ = false;
bool is_renaming_ = false;
/** See #is_search_highlight(). */
bool is_highlighted_search_ = false;
/** Cache filtered state here to avoid having to re-query. */
bool is_filtered_visible_ = true;
/**
* Typically, only items with children can be collapsed. However, in some cases it's important
* to draw collapsible items differently from non-collapsible ones, even if they don't have
* children currently.
*/
bool is_always_collapsible_ = false;
/** See #select_on_click_set(). */
bool select_on_click_ = false;
/** See #always_reactivate_on_click(). */
bool reactivate_on_click_ = false;
/** See #activate_for_context_menu_set(). */
bool activate_for_context_menu_ = false;
public:
virtual ~AbstractViewItem() = default;
virtual void build_context_menu(bContext &C, Layout &column) const;
/**
* Like #activate() but does not call #on_activate(). Use it to reflect changes in the active
* state that happened externally. Or to simply highlight the item as active without triggering
* activation with an `on_activate()` call. E.g. this is done when spawning a context menu if
* #activate_for_context_menu_set() wasn't called, to indicate which item the context menu
* belongs to.
*
* Can be overridden to customize behavior but should always call the base class implementation.
*
* \return true of the item was activated.
*/
virtual bool set_state_active();
/**
* Called when the view changes an item's state from inactive to active. Will only be called if
* the state change is triggered through the view, not through external changes. E.g. a click on
* an item calls it, a change in the value returned by #should_be_active() to reflect an external
* state change does not.
*/
virtual void on_activate(bContext &C);
/**
* If the result is not empty, it controls whether the item should be active or not, usually
* depending on the data that the view represents. Note that since this is meant to reflect
* externally managed state changes, #on_activate() will never be called if this returns true.
*/
virtual std::optional<bool> should_be_active() const;
virtual std::optional<bool> should_be_selected() const;
virtual void set_selected(const bool select);
/**
* Queries if the view item supports renaming in principle. Renaming may still fail, e.g. if
* another item is already being renamed.
*/
virtual bool supports_renaming() const;
/**
* Try renaming the item, or the data it represents. Can assume
* #AbstractViewItem::supports_renaming() returned true. Sub-classes that override this should
* usually call this, unless they have a custom #AbstractViewItem.matches() implementation.
*
* \return True if the renaming was successful.
*/
virtual bool rename(const bContext &C, StringRefNull new_name);
/**
* Get the string that should be used for renaming, typically the item's label. This string will
* not be modified, but if the renaming is canceled, the value will be reset to this.
*/
virtual StringRef get_rename_string() const;
/**
* If an item wants to support being dragged, it has to return a drag controller here.
* That is an object implementing #AbstractViewItemDragController.
*/
virtual std::unique_ptr<AbstractViewItemDragController> create_drag_controller() const;
/**
* If an item wants to support dropping data into it, it has to return a drop target here.
* That is an object implementing #DropTargetInterface.
*
* \note This drop target may be requested for each event. The view doesn't keep a drop target
* around currently. So it can not contain persistent state.
*/
virtual std::unique_ptr<DropTargetInterface> create_item_drop_target();
/**
* View types should implement this to return some name or identifier of the item, which is
* helpful for debugging (there's nothing to identify the item just from the #AbstractViewItem
* otherwise).
*/
virtual std::optional<std::string> debug_name() const;
bool is_filtered_visible() const;
/** Get the view this item is registered for using #AbstractView::register_item(). */
AbstractView &get_view() const;
/**
* Get the view item button (button of type #ButtonType::ViewItem) created for this item. Every
* visible item gets one during the layout building. Items that are not visible may not have one,
* so null is a valid return value.
*/
ui::ButtonViewItem *view_item_button() const;
/** Disable the interacting with this item, meaning the buttons drawn will be disabled and there
* will be no mouse hover feedback for the view row. */
void disable_interaction();
bool is_interactive() const;
void disable_activatable();
/**
* Configure this view item to only select/activate on mouse-click (i.e. when the mouse is
* pressed and released without much movement in-between); the default is to select/activate on
* mouse-press.
*/
void select_on_click_set();
bool is_select_on_click() const;
/** Call #on_activate() on every click on the item, even when the item was active before. */
void always_reactivate_on_click();
/** Call #on_activate() when spawning a context menu. Otherwise the item will only be highlighted
* as active to indicate where the context menu was spawned from. */
void activate_for_context_menu_set();
/**
* Activates this item, deactivates other items, and calls the #AbstractViewItem::on_activate()
* function. Should only be called when the item was activated through the view (e.g. through a
* click), not if the view reflects an external change (e.g.
* #AbstractViewItem::should_be_active() changes from returning false to returning true).
*
* Also ensures the item is selected if it's active.
*
* Requires the view to have completed reconstruction, see #is_reconstructed(). Otherwise the
* actual item state is unknown, possibly calling state-change update functions incorrectly.
*/
void activate(bContext &C);
/**
* If #activate_for_context_menu_set() was called, properly (re)activates the item including a
* #AbstractViewItem::on_activate() call. Otherwise, the item will only be highlighted as active,
* to indicate which item the context menu belongs to.
* Should be used when spawning a context menu for this item.
*/
void activate_for_context_menu(bContext &C);
void deactivate();
/**
* Is the item currently hovered by the mouse cursor? Can be used in the #build_
* Requires the view to have completed reconstruction, see #is_reconstructed(). Otherwise we
* can't be sure about the item state.
*/
bool is_hovered() const;
/**
* Requires the view to have completed reconstruction, see #is_reconstructed(). Otherwise we
* can't be sure about the item state.
*/
bool is_active() const;
bool is_selected() const;
/**
* Should this item be highlighted as matching search result? Only one item should be highlighted
* this way at a time. Pressing enter will activate it.
*/
bool is_search_highlight() const;
bool is_renaming() const;
void begin_renaming();
void end_renaming();
void rename_apply(const bContext &C);
virtual void delete_item(bContext *C);
virtual void on_filter();
protected:
AbstractViewItem() = default;
/**
* Compare this item's identity to \a other to check if they represent the same data.
* Implementations can assume that the types match already (caller must check).
*
* Used to recognize an item from a previous redraw, to be able to keep its state (e.g. active,
* renaming, etc.).
*/
virtual bool matches(const AbstractViewItem &other) const = 0;
/**
* Copy persistent state (e.g. active, selection, etc.) from a matching item of
* the last redraw to this item. If sub-classes introduce more advanced state they should
* override this and make it update their state accordingly.
*
* \note Always call the base class implementation when overriding this!
*/
virtual void update_from_old(const AbstractViewItem &old);
/**
* See #AbstractView::change_state_delayed(). Overrides should call the base class
* implementation.
*/
virtual void change_state_delayed();
/**
* \note Do not call this directly to avoid constantly rechecking the filter state. Instead use
* #is_filtered_visible() for querying.
*/
virtual bool should_be_filtered_visible(StringRefNull filter_string) const;
/**
* Add a text button for renaming the item to \a block. This must be used for the built-in
* renaming to work. This button is meant to appear temporarily. It is removed when renaming is
* done.
*/
void add_rename_button(Block &block);
};
/* ---------------------------------------------------------------------- */
/** \name Drag 'n Drop
* \{ */
/**
* Class to enable dragging a view item. An item can return a drag controller for itself by
* implementing #AbstractViewItem::create_drag_controller().
*/
class AbstractViewItemDragController {
protected:
AbstractView &view_;
public:
AbstractViewItemDragController(AbstractView &view);
virtual ~AbstractViewItemDragController() = default;
virtual std::optional<eWM_DragDataType> get_drag_type() const = 0;
virtual void *create_drag_data() const = 0;
/**
* Called when beginning to drag. Also called when #get_drag_type() doesn't return a value, so an
* arbitrary action can be executed.
* \param item: The item this drag controller was created from. It's passed so it doesn't have to
* be stored (especially as non-const).
*/
virtual void on_drag_start(bContext &C, ui::AbstractViewItem &item);
/** Request the view the item is registered for as type #ViewType. Throws a `std::bad_cast`
* exception if the view is not of the requested type. */
template<class ViewType> inline ViewType &get_view() const;
};
template<class ViewType> ViewType &AbstractViewItemDragController::get_view() const
{
static_assert(std::is_base_of_v<AbstractView, ViewType>,
"Type must derive from and implement the ui::AbstractView interface");
return dynamic_cast<ViewType &>(view_);
}
/** \} */
} // namespace ui
} // namespace blender

View File

@@ -0,0 +1,268 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editorui
*
* API for simple creation of grid UIs, supporting typically needed features.
* https://developer.blender.org/docs/features/interface/views/grid_views/
*/
#pragma once
#include <optional>
#include "BLI_function_ref.hh"
#include "BLI_map.hh"
#include "BLI_vector.hh"
#include "UI_abstract_view.hh"
#include "UI_resources.hh"
namespace blender {
struct bContext;
struct View2D;
namespace ui {
class AbstractGridView;
class GridViewItemDropTarget;
struct Layout;
/* ---------------------------------------------------------------------- */
/** \name Grid-View Item Type
* \{ */
class AbstractGridViewItem : public AbstractViewItem {
friend class AbstractGridView;
friend class GridViewLayoutBuilder;
protected:
/**
* A string that uniquely identifies this item in the view.
*
* Ideally this would just be a StringRef to save memory. This was made a
* std::string to fix #141882 in a relatively safe way. */
std::string identifier_{};
public:
/* virtual */ ~AbstractGridViewItem() override = default;
virtual void build_grid_tile(const bContext &C, Layout &layout) const = 0;
/* virtual */ std::optional<std::string> debug_name() const override;
AbstractGridView &get_view() const;
protected:
AbstractGridViewItem(StringRef identifier);
/** See AbstractViewItem::matches(). */
/* virtual */ bool matches(const AbstractViewItem &other) const override;
/* virtual */ std::unique_ptr<DropTargetInterface> create_item_drop_target() final;
virtual std::unique_ptr<GridViewItemDropTarget> create_drop_target();
private:
void add_grid_tile_button(Block &block);
};
/** \} */
/* ---------------------------------------------------------------------- */
/** \name Grid-View Base Class
* \{ */
struct GridViewStyle {
GridViewStyle(int width, int height);
int tile_width = 0;
int tile_height = 0;
};
class AbstractGridView : public AbstractView {
friend class AbstractGridViewItem;
friend class GridViewBuilder;
friend class GridViewLayoutBuilder;
protected:
Vector<std::unique_ptr<AbstractGridViewItem>> items_;
/** Store this to avoid recomputing. */
mutable std::optional<int> item_count_filtered_;
/** <identifier, item> map to lookup items by identifier, used for efficient lookups in
* #update_from_old(). */
Map<StringRef, AbstractGridViewItem *> item_map_;
GridViewStyle style_;
int cols_per_row_ = 0;
public:
AbstractGridView();
/* virtual */ ~AbstractGridView() override = default;
using ItemIterFn = FunctionRef<void(AbstractGridViewItem &)>;
void foreach_item(ItemIterFn iter_fn) const;
void foreach_filtered_item(ItemIterFn iter_fn) const;
/**
* Convenience wrapper constructing the item by forwarding given arguments to the constructor of
* the type (\a ItemT).
*
* E.g. if your grid-item type has the following constructor:
* \code{.cpp}
* MyGridItem(std::string str, int i);
* \endcode
* You can add an item like this:
* \code
* add_item<MyGridItem>("blabla", 42);
* \endcode
*/
template<class ItemT, typename... Args> inline ItemT &add_item(Args &&...args);
const GridViewStyle &get_style() const;
int get_item_count() const;
int get_item_count_filtered() const;
void set_tile_size(int tile_width, int tile_height);
AbstractViewItem *find_active_or_visible_item() const override;
AbstractViewItem *navigate_left(AbstractViewItem *from) override;
AbstractViewItem *navigate_right(AbstractViewItem *from) override;
AbstractViewItem *navigate_up(AbstractViewItem *from) override;
AbstractViewItem *navigate_down(AbstractViewItem *from) override;
void scroll_active_into_view(bContext *C, bool scroll_active_to_center = false) override;
IndexRange get_visible_range(const View2D &v2d,
const AbstractGridViewItem *force_visible_item) const;
protected:
virtual void build_items() = 0;
private:
void foreach_view_item(FunctionRef<void(AbstractViewItem &)> iter_fn) const final;
void update_children_from_old(const AbstractView &old_view) override;
AbstractGridViewItem *find_matching_item(const AbstractGridViewItem &item_to_match,
const AbstractGridView &view_to_search_in) const;
/**
* Add an already constructed item, moving ownership to the grid-view.
* All items must be added through this, it handles important invariants!
*/
AbstractGridViewItem &add_item(std::unique_ptr<AbstractGridViewItem> item);
};
/** \} */
/* ---------------------------------------------------------------------- */
/** \name Drag & Drop
* \{ */
/**
* Class to define the behavior when dropping something onto/into a view item, plus the behavior
* when dragging over this item. An item can return a drop target for itself via a custom
* implementation of #AbstractGridViewItem::create_drop_target().
*/
class GridViewItemDropTarget : public DropTargetInterface {
protected:
AbstractGridView &view_;
public:
GridViewItemDropTarget(AbstractGridView &view);
/** Request the view the item is registered for as type #ViewType. Throws a `std::bad_cast`
* exception if the view is not of the requested type. */
template<class ViewType> inline ViewType &get_view() const;
};
/** \} */
/* ---------------------------------------------------------------------- */
/** \name Grid-View Builder
*
* TODO unify this with `TreeViewBuilder` and call view-specific functions via type erased view?
* \{ */
class GridViewBuilder {
public:
GridViewBuilder(Block &block);
void build_grid_view(const bContext &C,
AbstractGridView &grid_view,
Layout &layout,
std::optional<StringRef> search_string = {});
};
/** \} */
/* ---------------------------------------------------------------------- */
/** \name Predefined Grid-View Item Types
*
* Common, Basic Grid-View Item Types.
* \{ */
/**
* A grid item that shows preview image icons at a nicely readable size (multiple of the normal UI
* unit size).
*/
class PreviewGridItem : public AbstractGridViewItem {
public:
using IsActiveFn = std::function<bool()>;
using ActivateFn = std::function<void(bContext &C, PreviewGridItem &new_active)>;
protected:
/** See #set_on_activate_fn() */
ActivateFn activate_fn_;
/** See #set_is_active_fn() */
IsActiveFn is_active_fn_;
bool hide_label_ = false;
public:
std::string label;
int preview_icon_id = ICON_NONE;
PreviewGridItem(StringRef identifier, StringRef label, int preview_icon_id);
void build_grid_tile(const bContext &C, Layout &layout) const override;
void build_grid_tile_button(Layout &layout,
BIFIconID override_preview_icon_id = ICON_NONE) const;
/**
* Set a custom callback to execute when activating this view item. This way users don't have to
* sub-class #PreviewGridItem, just to implement custom activation behavior (a common thing to
* do).
*/
void set_on_activate_fn(ActivateFn fn);
/**
* Set a custom callback to check if this item should be active.
*/
void set_is_active_fn(IsActiveFn fn);
void hide_label();
private:
std::optional<bool> should_be_active() const override;
void on_activate(bContext &C) override;
};
/** \} */
/* ---------------------------------------------------------------------- */
template<class ItemT, typename... Args> inline ItemT &AbstractGridView::add_item(Args &&...args)
{
static_assert(std::is_base_of_v<AbstractGridViewItem, ItemT>,
"Type must derive from and implement the AbstractGridViewItem interface");
return dynamic_cast<ItemT &>(add_item(std::make_unique<ItemT>(std::forward<Args>(args)...)));
}
template<class ViewType> ViewType &GridViewItemDropTarget::get_view() const
{
static_assert(std::is_base_of_v<AbstractGridView, ViewType>,
"Type must derive from and implement the ui::AbstractGridView interface");
return dynamic_cast<ViewType &>(view_);
}
} // namespace ui
} // namespace blender

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,291 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editorui
*/
#pragma once
#include <functional>
#include <memory>
#include "BLI_function_ref.hh"
#include "BLI_string_ref.hh"
#include "BLI_vector.hh"
#include "UI_resources.hh"
#include "UI_interface_c.hh" // IWYU pragma: export
namespace blender {
namespace nodes::eval_log {
struct GeometryAttributeInfo;
}
struct ARegion;
struct bContext;
struct PointerRNA;
struct StructRNA;
struct uiList;
struct wmDrag;
struct wmEvent;
namespace ui {
class AbstractView;
class AbstractViewItem;
struct Layout;
struct SearchItems;
void button_func_set(Button *but, std::function<void(bContext &)> func);
void button_func_pushed_state_set(Button *but, std::function<bool(const Button &)> func);
/**
* Template generating a freeing callback matching the #uiButArgNFree signature, for data created
* with #MEM_new.
*/
template<typename T> void but_func_argN_free(void *argN)
{
MEM_delete(static_cast<T *>(argN));
}
/**
* Template generating a copying callback matching the #uiButArgNCopy signature, for data created
* with #MEM_new.
*/
template<typename T> void *but_func_argN_copy(const void *argN)
{
return MEM_new<T>(__func__, *static_cast<const T *>(argN));
}
class AbstractGridView;
class AbstractTreeView;
class DropTargetInterface;
/**
* An item in a breadcrumb-like context. Currently this struct is very simple, but more
* could be added to it in the future, to support interactivity or tooltips, for example.
*/
struct ContextPathItem {
/* Text to display in the UI. */
std::string name;
/* #BIFIconID */
int icon;
int icon_indicator_number;
std::function<void(bContext &)> handle_func;
};
void context_path_add_generic(Vector<ContextPathItem> &path,
StructRNA &rna_type,
void *ptr,
const BIFIconID icon_override = ICON_NONE,
std::function<void(bContext &)> handle_func = nullptr);
void template_breadcrumbs(Layout &layout, Span<ContextPathItem> context_path);
void attribute_search_add_items(StringRef str,
bool can_create_attribute,
Span<const nodes::eval_log::GeometryAttributeInfo *> infos,
SearchItems *items,
bool is_first);
void grease_pencil_layer_search_add_items(StringRef str,
Span<const std::string *> layer_names,
SearchItems &items,
bool is_first);
bool asset_shelf_popover_invoke(bContext &C, StringRef asset_shelf_idname, ReportList &reports);
/**
* Some drop targets simply allow dropping onto/into them, others support dragging in-between them.
* Classes implementing the drop-target interface can use this type to control the behavior by
* letting it influence the result of #choose_drop_location().
*/
enum class DropBehavior {
/**
* Enable dropping before (#DropLocation::Before) and after (#DropLocation::After) the
* drop target. Typically used for reordering items.
*/
Reorder,
/** Only enable dropping onto/into the drop target (#DropLocation::Into). */
Insert,
/**
* Enable dropping onto/into (#DropLocation::Into), before (#DropLocation::Before) and after
* (#DropLocation::After) the drop target. Typically used for reordering items with nesting
* support. */
ReorderAndInsert,
};
/**
* Information on how dragged data should be inserted on drop, as determined through
* #DropTargetInterface::choose_drop_location(). Also see #DropBehavior.
*/
enum class DropLocation {
Into,
Before,
After,
};
/**
* Information passed to drop targets while dragging over them.
*/
struct DragInfo {
const wmDrag &drag_data;
const wmEvent &event;
const DropLocation drop_location;
DragInfo(const wmDrag &drag, const wmEvent &event, DropLocation drop_location);
};
/**
* This provides a common interface for UI elements that want to support dragging & dropping
* entities into/onto them. With it, the element can determine if the dragged entity can be dropped
* onto itself, provide feedback while dragging and run custom code for the dropping.
*
* By default the drop target behaves so that data can be dragged into or onto it.
* #choose_drop_location() can be overridden to change that.
*
* Note that this is just an interface (not in the strict sense of a Java/C# interface though). A
* #wmDropBox is needed to request instances of it from a UI element and call its functions. For
* example the drop box using "UI_OT_view_drop" implements dropping for views and view items via
* this interface. To support other kinds of UI elements, similar drop boxes would be necessary.
*/
class DropTargetInterface {
public:
DropTargetInterface() = default;
virtual ~DropTargetInterface() = default;
/**
* Check if the data dragged with \a drag can be dropped on the element this drop target is for.
* \param r_disabled_hint: Return a static string to display to the user, explaining why dropping
* isn't possible on this UI element. Shouldn't be done too aggressively,
* e.g. don't set this if the drag-type can't be dropped here; only if it
* can but there's another reason it can't be dropped. Can assume this is
* a non-null pointer.
*/
virtual bool can_drop(const wmDrag &drag, const char **r_disabled_hint) const = 0;
/**
* Once the drop target validated that it can receive the dragged data using #can_drop(), this
* method can determine where/how the data should be dropped exactly: before, after or into the
* drop target. Additional feedback can be drawn then while dragging, and the #on_drop() function
* should operate accordingly. Implementations of this function may want to use #DropBehavior to
* control which locations may be returned here.
*
* If the returned optional is unset, dropping will be disabled. The default implementation
* returns #DropLocation::Into.
*/
virtual std::optional<DropLocation> choose_drop_location(const ARegion &region,
const wmEvent &event) const;
/**
* Custom text to display when dragging over the element using this drop target. Should
* explain what happens when dropping the data onto this UI element. Will only be used if
* #DropTargetInterface::can_drop() returns true, so the implementing override doesn't have
* to check that again. The returned value must be a translated string.
*/
virtual std::string drop_tooltip(const DragInfo &drag) const = 0;
/**
* Execute the logic to apply a drop of the data dragged with \a drag onto/into the UI element
* this drop target is for.
*/
virtual bool on_drop(bContext *C, const DragInfo &drag) const = 0;
};
/**
* Let a drop target handle a drop event.
* \return True if the dropping was successful.
*/
bool drop_target_apply_drop(bContext &C,
const ARegion &region,
const wmEvent &event,
const DropTargetInterface &drop_target,
const ListBaseT<wmDrag> &drags);
/**
* Call #DropTargetInterface::drop_tooltip() and return the result as newly allocated C string
* (unless the result is empty, returns null then). Needs freeing with MEM_delete().
*/
std::string drop_target_tooltip(const ARegion &region,
const DropTargetInterface &drop_target,
const wmDrag &drag,
const wmEvent &event);
/**
* Try to find a view item with a drop target under the mouse cursor, or if not found, a view
* with a drop target.
* \param xy: Coordinate to find a drop target at, in window space.
*/
std::unique_ptr<DropTargetInterface> region_views_find_drop_target_at(const ARegion *region,
const int xy[2]);
enum eUIListFilterResult {
/** Never show this item, even when filter results are inverted (#UILST_FLT_EXCLUDE). */
UI_LIST_ITEM_NEVER_SHOW,
/** Show this item, unless filter results are inverted (#UILST_FLT_EXCLUDE). */
UI_LIST_ITEM_FILTER_MATCHES,
/** Don't show this item, unless filter results are inverted (#UILST_FLT_EXCLUDE). */
UI_LIST_ITEM_FILTER_MISMATCHES,
};
/**
* Function object for UI list item filtering that does the default name comparison with '*'
* wildcards. Create an instance of this once and pass it to #uilist_filter_and_sort_items(), do
* NOT create an instance for every item, this would be costly.
*/
class uiListNameFilter {
/* Storage with an inline buffer for smaller strings (small buffer optimization). */
struct {
char filter_buff[32];
char *filter_dyn = nullptr;
} storage_;
char *filter_ = nullptr;
public:
uiListNameFilter(uiList &list);
~uiListNameFilter();
eUIListFilterResult operator()(const PointerRNA &itemptr, StringRefNull name, int index);
};
using uiListItemFilterFn =
FunctionRef<eUIListFilterResult(const PointerRNA &itemptr, StringRefNull name, int index)>;
using uiListItemGetNameFn = FunctionRef<std::string(const PointerRNA &itemptr, int index)>;
/**
* Helper to apply custom filtering to UI lists not defined in Python. Custom filtering for
* Python UI lists has own code. This is also used as the default filtering if no
* #uiListType::filter_items callback is set.
*
* Filters list items using \a item_filter_fn and sorts the result. Also handles alphabetical
* sorting (#UILST_FLT_SORT_ALPHA), and result inverting (#UILST_FLT_EXCLUDE) if enabled, so the
* callback doesn't have to do this (unlike the filter function in Python).
*
* Call this from a #uiListType::filter_items callback with any #item_filter_fn. #uiListNameFilter
* can be used to apply the default name based filtering.
*
* \param get_name_fn: In some cases the name cannot be retrieved via RNA. This function can be set
* to provide the name still.
*/
void uilist_filter_and_sort_items(uiList *ui_list,
const bContext *C,
uiListItemFilterFn item_filter_fn,
PointerRNA *dataptr,
const char *propname,
uiListItemGetNameFn get_name_fn = nullptr);
/**
* Override this for all available view types.
* \param idname: Used for restoring persistent state of this view, potentially written to files.
* Must not be longer than #BKE_ST_MAXNAME (including 0 terminator).
*/
AbstractGridView *block_add_view(Block &block,
StringRef idname,
std::unique_ptr<AbstractGridView> grid_view);
AbstractTreeView *block_add_view(Block &block,
StringRef idname,
std::unique_ptr<AbstractTreeView> tree_view);
void alert(bContext *C, StringRef title, StringRef message, AlertIcon icon, bool compact);
} // namespace ui
} // namespace blender

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,127 @@
/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editorui
*/
#pragma once
#include "BLI_sys_types.h"
/* Required for #eIconSizes. */
#include "DNA_ID_enums.h"
namespace blender {
struct Collection;
struct ID;
struct ImBuf;
struct Object;
struct PointerRNA;
struct PreviewImage;
struct Scene;
struct bContext;
namespace ui {
struct IconTextOverlay {
char text[5];
uchar color[4] = {0};
};
#define UI_NO_ICON_OVERLAY_TEXT NULL
#define ICON_DEFAULT_HEIGHT 16
#define ICON_DEFAULT_WIDTH 16
#define ICON_DEFAULT_HEIGHT_TOOLBAR 32
#define ICON_DEFAULT_HEIGHT_SCALE int(UI_UNIT_Y * 0.8f)
#define ICON_DEFAULT_WIDTH_SCALE int(UI_UNIT_X * 0.8f)
#define PREVIEW_DEFAULT_HEIGHT 128
#define PREVIEW_DRAG_DRAW_SIZE 96.0f
enum class AlertIcon : int8_t {
None = -1,
Warning = 0,
Question = 1,
Error = 2,
Info = 3,
Max,
};
ImBuf *icon_alert_imbuf_get(AlertIcon icon, float size);
/**
* Resizable Icons for Blender
*/
void icons_init();
bool icon_get_theme_color(int icon_id, unsigned char color[4]);
/**
* Render a #PreviewImage for the data block.
*
* Note that if an ID doesn't support jobs for preview creation, \a use_job will be ignored.
*/
void icon_render_id(const bContext *C, Scene *scene, ID *id, enum eIconSizes size, bool use_job);
/**
* Render the data block into the provided #PreviewImage.
*/
void icon_render_id_ex(const bContext *C,
Scene *scene,
ID *id_to_render,
const enum eIconSizes size,
const bool use_job,
PreviewImage *r_preview_image);
/**
* Render size for preview images and icons
*/
int icon_preview_to_render_size(enum eIconSizes size);
/**
* Draws icon with DPI scale factor.
*/
void icon_draw(float x, float y, int icon_id);
void icon_draw_alpha(float x, float y, int icon_id, float alpha);
void icon_draw_preview(float x, float y, int icon_id, float aspect, float alpha, int size);
void icon_draw_ex(float x,
float y,
int icon_id,
float aspect,
float alpha,
float desaturate,
const uchar mono_color[4],
bool mono_border,
const IconTextOverlay *text_overlay,
const bool inverted = false,
float scale = 1.0f);
ImBuf *svg_icon_bitmap(uint icon_id, float size, bool multicolor = false);
void icons_free();
void icons_free_drawinfo(void *drawinfo);
PreviewImage *icon_to_preview(int icon_id);
int icon_from_rnaptr(const bContext *C, PointerRNA *ptr, int rnaicon, bool big);
int icon_from_idcode(int idcode);
int icon_from_library(const ID *id);
int icon_from_object_mode(int mode);
int icon_from_object_type(const Object *object);
int icon_color_from_collection(const Collection *collection);
void icon_text_overlay_init_from_count(IconTextOverlay *text_overlay,
const int icon_indicator_number);
void icon_ensure_deferred(const bContext *C, int icon_id, bool big);
} // namespace ui
} // namespace blender

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,62 @@
/* SPDX-FileCopyrightText: 2025 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#include <string>
#include "BLI_string_ref.hh"
namespace blender {
struct bContext;
namespace ui {
struct Block;
struct Button;
struct Layout;
struct TooltipData;
/* names */
#define UI_MAX_DRAW_STR 550
#define UI_MAX_NAME_STR 256
#define UI_MAX_SHORTCUT_STR 64
#define RNA_NO_INDEX -1
/* Menu Callbacks */
using MenuCreateFunc = void (*)(bContext *C, Layout *layout, void *arg1);
using MenuHandleFunc = void (*)(bContext *C, void *arg, int event);
/**
* Used for cycling menu values without opening the menu (Ctrl-Wheel).
* \param direction: forward or backwards [1 / -1].
* \param arg1: `Button.poin` (as with #MenuCreateFunc).
* \return true when the button was changed.
*/
using MenuStepFunc = bool (*)(bContext *C, int direction, void *arg1);
using CopyArgFunc = void *(*)(const void *arg);
using FreeArgFunc = void (*)(void *arg);
/** Must return an allocated string. */
using ButtonToolTipFunc = std::string (*)(bContext *C, void *argN, StringRef tip);
/**
* \param data: The tooltip data to be filled.
* \param but: The exact button the tooltip is shown for. This is needed when the tooltip function
* is shared across multiple buttons but there still needs to be some customization per button.
* Mostly useful when using #uiLayoutSetTooltipCustomFunc.
*/
using ButtonToolTipCustomFunc = void (*)(bContext &C, TooltipData &data, Button *but, void *argN);
} // namespace ui
namespace ocio {
class Display;
} // namespace ocio
using ColorManagedDisplay = ocio::Display;
} // namespace blender

View File

@@ -0,0 +1,534 @@
/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editorui
*/
#pragma once
#include "BLI_assert.h"
namespace blender {
struct bTheme;
/* Define icon enum. */
#define DEF_ICON(name) ICON_##name,
#define DEF_ICON_VECTOR(name) ICON_##name,
#define DEF_ICON_COLOR(name) ICON_##name,
#define DEF_ICON_BLANK(name) ICON_BLANK_##name,
/**
* Builtin icons with a compile-time icon-id. Dynamically created icons such as preview image
* icons get a dynamic icon-id <= #BIFICONID_LAST_STATIC, #BIFIconID can hold both.
*/
enum BIFIconID_Static {
/* ui */
#include "UI_icons.hh"
BIFICONID_LAST_STATIC,
};
/** Type that fits all compile time and dynamic icon-ids. */
using BIFIconID = int;
BLI_STATIC_ASSERT(sizeof(BIFIconID_Static) <= sizeof(BIFIconID),
"Expected all builtin icon IDs to fit into `BIFIconID`");
#define BIFICONID_FIRST (ICON_NONE)
/* use to denote intentionally unset theme color */
#define TH_UNDEFINED -1
enum ThemeColorID {
TH_NONE,
TH_BLACK,
TH_WHITE,
TH_REDALERT,
TH_ERROR,
TH_WARNING,
TH_INFO,
TH_SUCCESS,
TH_LINK,
TH_THEMEUI,
/* Common colors among spaces. */
TH_BACK,
/** Use when 'TH_SHOW_BACK_GRAD' is set (the lower, darker color). */
TH_BACK_GRAD,
TH_TEXT,
TH_TEXT_HI,
TH_TITLE,
/* Tabs. */
TH_TAB_TEXT,
TH_TAB_TEXT_HI,
TH_TAB_ACTIVE,
TH_TAB_INACTIVE,
TH_TAB_BACK,
TH_TAB_OUTLINE,
TH_TAB_OUTLINE_ACTIVE,
TH_HEADER,
TH_HEADER_TEXT,
TH_HEADER_TEXT_HI,
/* panels */
TH_PANEL_HEADER,
TH_PANEL_BACK,
TH_PANEL_SUB_BACK,
TH_PANEL_OUTLINE,
TH_PANEL_ACTIVE,
TH_SHADE1,
TH_SHADE2,
TH_HILITE,
TH_GRID,
TH_GRID_MAJOR,
TH_WIRE,
TH_WIRE_INNER,
TH_WIRE_EDIT,
TH_SELECT,
TH_ACTIVE,
TH_GROUP,
TH_GROUP_ACTIVE,
TH_TRANSFORM,
TH_VERTEX,
TH_VERTEX_SELECT,
TH_VERTEX_ACTIVE,
TH_VERTEX_UNREFERENCED,
TH_VERTEX_SIZE,
TH_EDGE_WIDTH,
TH_OUTLINE_WIDTH,
TH_OBCENTER_DIA,
TH_EDGE,
TH_EDGE_SELECT, /* Stands for edge selection, not edge select mode. */
TH_EDGE_MODE_SELECT,
TH_FACE,
TH_FACE_SELECT, /* Stands for face selection, not face select mode. */
TH_FACE_MODE_SELECT,
TH_FACE_RETOPOLOGY,
TH_FACE_BACK,
TH_FACE_FRONT,
TH_NORMAL,
TH_VNORMAL,
TH_LNORMAL,
TH_FACEDOT_SIZE,
TH_CFRAME,
TH_FRAME_BEFORE,
TH_FRAME_AFTER,
TH_TIME_SCRUB_BACKGROUND,
TH_TIME_SCRUB_TEXT,
TH_TIME_MARKER_LINE,
TH_TIME_MARKER_LINE_SELECTED,
TH_TIME_GP_KEYFRAME,
TH_NURB_ULINE,
TH_NURB_VLINE,
TH_NURB_SEL_ULINE,
TH_NURB_SEL_VLINE,
/* this eight colors should be in one block */
TH_HANDLE_FREE,
TH_HANDLE_AUTO,
TH_HANDLE_VECT,
TH_HANDLE_ALIGN,
TH_HANDLE_AUTOCLAMP,
TH_HANDLE_SEL_FREE,
TH_HANDLE_SEL_AUTO,
TH_HANDLE_SEL_VECT,
TH_HANDLE_SEL_ALIGN,
TH_HANDLE_SEL_AUTOCLAMP,
TH_SYNTAX_B,
TH_SYNTAX_V,
TH_SYNTAX_R,
TH_SYNTAX_C,
TH_SYNTAX_L,
TH_SYNTAX_D,
TH_SYNTAX_N,
TH_SYNTAX_S,
TH_LINENUMBERS,
TH_BONE_SOLID,
TH_BONE_POSE,
TH_BONE_POSE_ACTIVE,
TH_BONE_LOCKED_WEIGHT,
TH_STRIP,
TH_STRIP_SELECT,
TH_CHANNEL,
TH_CHANNEL_SELECT,
TH_LONGKEY,
TH_LONGKEY_SELECT,
TH_KEYTYPE_KEYFRAME, /* KEYTYPES */
TH_KEYTYPE_KEYFRAME_SELECT,
TH_KEYTYPE_EXTREME,
TH_KEYTYPE_EXTREME_SELECT,
TH_KEYTYPE_BREAKDOWN,
TH_KEYTYPE_BREAKDOWN_SELECT,
TH_KEYTYPE_JITTER,
TH_KEYTYPE_JITTER_SELECT,
TH_KEYTYPE_MOVEHOLD,
TH_KEYTYPE_MOVEHOLD_SELECT,
TH_KEYTYPE_GENERATED,
TH_KEYTYPE_GENERATED_SELECT,
TH_KEYBORDER,
TH_KEYBORDER_SELECT,
TH_LIGHT,
TH_SPEAKER,
TH_CAMERA,
TH_EMPTY,
TH_NODE,
TH_NODE_OUTLINE,
TH_NODE_INPUT,
TH_NODE_OUTPUT,
TH_NODE_COLOR,
TH_NODE_FILTER,
TH_NODE_VECTOR,
TH_NODE_TEXTURE,
TH_NODE_SCRIPT,
TH_NODE_SHADER,
TH_NODE_INTERFACE,
TH_NODE_CONVERTER,
TH_NODE_GROUP,
TH_NODE_FRAME,
TH_NODE_MATTE,
TH_NODE_DISTORT,
TH_NODE_GEOMETRY,
TH_NODE_ATTRIBUTE,
TH_NODE_ZONE_SIMULATION,
TH_NODE_ZONE_REPEAT,
TH_NODE_ZONE_FOREACH_GEOMETRY_ELEMENT,
TH_NODE_ZONE_CLOSURE,
TH_SIMULATED_FRAMES,
TH_CONSOLE_OUTPUT,
TH_CONSOLE_INPUT,
TH_CONSOLE_INFO,
TH_CONSOLE_ERROR,
TH_CONSOLE_CURSOR,
TH_CONSOLE_SELECT,
TH_SEQ_MOVIE,
TH_SEQ_MOVIECLIP,
TH_SEQ_MASK,
TH_SEQ_IMAGE,
TH_SEQ_SCENE,
TH_SEQ_AUDIO,
TH_SEQ_EFFECT,
TH_SEQ_TRANSITION,
TH_SEQ_META,
TH_SEQ_TEXT,
TH_SEQ_PREVIEW,
TH_SEQ_COLOR,
TH_SEQ_ACTIVE,
TH_SEQ_SELECTED,
TH_SEQ_TEXT_CURSOR,
TH_SEQ_SELECTED_TEXT,
TH_EDITMESH_ACTIVE,
TH_HANDLE_VERTEX,
TH_HANDLE_VERTEX_SELECT,
TH_HANDLE_VERTEX_SIZE,
TH_GP_WIRE_EDIT,
TH_GP_VERTEX,
TH_GP_VERTEX_SELECT,
TH_GP_VERTEX_SIZE,
TH_DOPESHEET_CHANNELOB,
TH_DOPESHEET_CHANNELSUBOB,
TH_DOPESHEET_IPOLINE,
TH_DOPESHEET_IPOCONST,
TH_DOPESHEET_IPOOTHER,
TH_PREVIEW_BACK,
TH_DRAWEXTRA_EDGELEN,
TH_DRAWEXTRA_EDGEANG,
TH_DRAWEXTRA_FACEAREA,
TH_DRAWEXTRA_FACEANG,
TH_NODE_CURVING,
TH_NODE_GRID_LEVELS,
TH_MARKER_OUTLINE,
TH_MARKER,
TH_ACT_MARKER,
TH_SEL_MARKER,
TH_BUNDLE_SOLID,
TH_DIS_MARKER,
TH_PATH_BEFORE,
TH_PATH_AFTER,
TH_PATH_KEYFRAME_BEFORE,
TH_PATH_KEYFRAME_AFTER,
TH_CAMERA_PATH,
TH_CAMERA_PASSEPARTOUT,
TH_LOCK_MARKER,
TH_STITCH_PREVIEW_FACE,
TH_STITCH_PREVIEW_EDGE,
TH_STITCH_PREVIEW_VERT,
TH_STITCH_PREVIEW_STITCHABLE,
TH_STITCH_PREVIEW_UNSTITCHABLE,
TH_STITCH_PREVIEW_ACTIVE,
TH_UV_SHADOW,
TH_MATCH, /* highlight color for search matches */
TH_SELECT_HIGHLIGHT, /* highlight color for selected outliner item */
TH_SELECT_ACTIVE, /* highlight color for active outliner item */
TH_SELECTED_OBJECT, /* selected object color for outliner */
TH_ACTIVE_OBJECT, /* active object color for outliner */
TH_EDITED_OBJECT, /* edited object color for outliner */
TH_ROW_ALTERNATE, /* overlay on every other row */
TH_SKIN_ROOT,
TH_ANIM_ACTIVE, /* active action */
TH_ANIM_INACTIVE, /* no active action */
TH_ANIM_PREVIEW_RANGE, /* preview range overlay */
TH_ANIM_SCENE_STRIP_RANGE, /* scene strip range overlay */
TH_ICON_SCENE,
TH_ICON_COLLECTION,
TH_ICON_OBJECT,
TH_ICON_OBJECT_DATA,
TH_ICON_MODIFIER,
TH_ICON_SHADING,
TH_ICON_FOLDER,
TH_ICON_AUTOKEY,
TH_ICON_FUND,
TH_SCROLL_TEXT,
TH_NLA_TWEAK, /* 'tweaking' track in NLA */
TH_NLA_TWEAK_DUPLI, /* error/warning flag for other strips referencing dupli strip */
TH_NLA_TRACK,
TH_NLA_TRANSITION,
TH_NLA_TRANSITION_SEL,
TH_NLA_META,
TH_NLA_META_SEL,
TH_NLA_SOUND,
TH_NLA_SOUND_SEL,
TH_WIDGET_EMBOSS,
TH_WIDGET_TEXT_CURSOR,
TH_WIDGET_TEXT_SELECTION,
TH_WIDGET_TEXT_HIGHLIGHT,
TH_EDITOR_OUTLINE,
TH_EDITOR_OUTLINE_ACTIVE,
TH_EDITOR_BORDER,
TH_TRANSPARENT_CHECKER_PRIMARY,
TH_TRANSPARENT_CHECKER_SECONDARY,
TH_TRANSPARENT_CHECKER_SIZE,
TH_AXIS_X, /* X/Y/Z Axis */
TH_AXIS_Y,
TH_AXIS_Z,
TH_AXIS_W, /* W (quaternion and axis-angle rotations) */
TH_GIZMO_HI,
TH_GIZMO_PRIMARY,
TH_GIZMO_SECONDARY,
TH_GIZMO_VIEW_ALIGN,
TH_GIZMO_A,
TH_GIZMO_B,
TH_BACKGROUND_TYPE,
TH_INFO_SELECTED,
TH_INFO_SELECTED_TEXT,
TH_INFO_ERROR_TEXT,
TH_INFO_WARNING_TEXT,
TH_INFO_INFO_TEXT,
TH_INFO_DEBUG,
TH_INFO_DEBUG_TEXT,
TH_INFO_PROPERTY,
TH_INFO_PROPERTY_TEXT,
TH_INFO_OPERATOR,
TH_INFO_OPERATOR_TEXT,
TH_VIEW_OVERLAY,
TH_V3D_CLIPPING_BORDER,
TH_METADATA_BG,
TH_METADATA_TEXT,
TH_BEVEL,
TH_CREASE,
TH_SEAM,
TH_SHARP,
TH_FREESTYLE,
};
namespace ui::theme {
/* Specific defines per space should have higher define values. */
struct bThemeState {
bTheme *theme;
int spacetype, regionid;
};
/* THE CODERS API FOR THEMES: */
/**
* Get individual values, not scaled.
*/
float get_value_f(int colorid);
/**
* Get individual values, not scaled.
*/
int get_value(int colorid);
/* Versions of #get_value & #get_value_f, which take a space-type */
float get_value_type_f(int colorid, int spacetype);
int get_value_type(int colorid, int spacetype);
/**
* Get three color values, scaled to 0.0-1.0 range.
*/
void get_color_3fv(int colorid, float col[3]);
void get_color_blend_3ubv(int colorid1, int colorid2, float fac, unsigned char col[3]);
void get_color_blend_3f(int colorid1, int colorid2, float fac, float r_col[3]);
void get_color_blend_4f(int colorid1, int colorid2, float fac, float r_col[4]);
/**
* Get the color, range 0.0-1.0, complete with shading offset.
*/
void get_color_shade_3fv(int colorid, int offset, float col[3]);
void get_color_shade_3ubv(int colorid, int offset, unsigned char col[3]);
void get_color_shade_4ubv(int colorid, int offset, unsigned char col[4]);
/**
* Get three color values, range 0-255,
* complete with shading offset for the RGB components and blending.
*/
void get_color_blend_shade_3ubv(
int colorid1, int colorid2, float fac, int offset, unsigned char col[3]);
/**
* Get four color values, scaled to 0.0-1.0 range.
*/
void get_color_4fv(int colorid, float col[4]);
/**
* Get four color values from specified space type, scaled to 0.0-1.0 range.
*/
void get_color_type_4fv(int colorid, int spacetype, float col[4]);
/**
* Get four color values, range 0.0-1.0, complete with shading offset for the RGB components.
*/
void get_color_shade_4fv(int colorid, int offset, float col[4]);
void get_color_shade_alpha_4fv(int colorid, int coloffset, int alphaoffset, float col[4]);
/**
* Get four color values ranged between 0 and 255; includes the alpha channel.
*/
void get_color_shade_alpha_4ubv(int colorid, int coloffset, int alphaoffset, unsigned char col[4]);
/**
* Get four color values, range 0.0-1.0,
* complete with shading offset for the RGB components and blending.
*/
void get_color_blend_shade_3fv(int colorid1, int colorid2, float fac, int offset, float col[3]);
void get_color_blend_shade_4fv(int colorid1, int colorid2, float fac, int offset, float col[4]);
/**
* Get the 3 or 4 byte values.
*/
void get_color_3ubv(int colorid, unsigned char col[3]);
/**
* Get the color, in char pointer.
*/
void get_color_4ubv(int colorid, unsigned char col[4]);
/**
* Get a theme color from specified space type.
*/
void get_color_type_3fv(int colorid, int spacetype, float col[3]);
void get_color_type_3ubv(int colorid, int spacetype, unsigned char col[3]);
void get_color_type_4ubv(int colorid, int spacetype, unsigned char col[4]);
/**
* Get theme color for coloring monochrome icons.
*/
bool get_icon_color_4ubv(int colorid, unsigned char col[4]);
/**
* Get four color values, range 0.0-1.0, blended between two other float color pointers,
* complete with offset for the alpha component.
*/
void get_color_blend_alpha_4fv(
const float cp1[4], const float cp2[4], float fac, float alphaoffset, float r_col[4]);
/**
* Shade a 3 byte color (same as get_color_blend_shade_3ubv with 0.0 factor).
*/
void get_color_shade_3ubv(const unsigned char cp[3], int offset, unsigned char r_col[3]);
/**
* Get a 3 byte color, blended and shaded between two other char color pointers.
*/
void get_color_blend_shade_3ubv(const unsigned char cp1[3],
const unsigned char cp2[3],
float fac,
int offset,
unsigned char r_col[3]);
/**
* Sets the font color
* (for anything fancy use GetThemeColor[Fancy] then BLF_color).
*/
void font_theme_color_set(int fontid, int colorid);
/**
* Clear the frame-buffer using the input colorid.
*/
void frame_buffer_clear(int colorid);
/**
* Internal (blender) usage only, for init and set active.
*/
void theme_set(int spacetype, int regionid);
/**
* Get current theme.
*/
bTheme *theme_get();
/**
* For the rare case we need to temp swap in a different theme (off-screen render).
*/
void theme_store(bThemeState *theme_state);
void theme_restore(const bThemeState *theme_state);
/**
* Return shadow width outside menus and popups.
*/
int get_menu_shadow_width();
/**
* Only for buttons in theme editor!
*/
const unsigned char *get_color_ptr(bTheme *btheme, int spacetype, int colorid);
void make_axis_color(const unsigned char col[3], char axis, unsigned char r_col[3]);
} // namespace ui::theme
} // namespace blender

View File

@@ -0,0 +1,38 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#include "BLI_string_search.hh"
namespace blender::ui::string_search {
/**
* Remember the string that the user chose. This allows us to put it higher up in the search items
* later on.
*/
void add_recent_search(StringRef chosen_str);
/**
* Depending on the user preferences, either outputs the recent cache or null.
*/
const blender::string_search::RecentCache *get_recent_cache_or_null();
void write_recent_searches_file();
void read_recent_searches_file();
/**
* Wrapper for the lower level #StringSearch in `blenlib` that takes recent searches into account
* automatically.
*/
template<typename T> class StringSearch : public blender::string_search::StringSearch<T> {
public:
StringSearch(const blender::string_search::MainWordsHeuristic main_word_heuristic =
blender::string_search::MainWordsHeuristic::LastGroup)
: blender::string_search::StringSearch<T>(get_recent_cache_or_null(), main_word_heuristic)
{
}
};
} // namespace blender::ui::string_search

View File

@@ -0,0 +1,490 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editorui
*
* API for simple creation of tree UIs supporting typically needed features.
* https://developer.blender.org/docs/features/interface/views/tree_views/
*/
#pragma once
#include <functional>
#include <memory>
#include <string>
#include "BLI_enum_flags.hh"
#include "BLI_vector.hh"
#include "UI_abstract_view.hh"
namespace blender {
struct bContext;
namespace ui {
class AbstractTreeView;
class AbstractTreeViewItem;
class TreeViewItemDropTarget;
struct Layout;
enum class TreeViewSortOrder : uint8_t {
None = 0,
InvertRoot = 1,
InvertNested = 2,
};
/* ---------------------------------------------------------------------- */
/** \name Tree-View Item Container
*
* Base class for tree-view and tree-view items, so both can contain children.
* \{ */
/**
* Both the tree-view (as the root of the tree) and the items can have children. This is the base
* class for both, to store and manage child items. Children are owned by their parent container
* (tree-view or item).
*
* That means this type can be used whenever either an #AbstractTreeView or an
* #AbstractTreeViewItem is needed, but the #TreeViewOrItem alias is a better name to use then.
*/
class TreeViewItemContainer {
friend class AbstractTreeView;
friend class AbstractTreeViewItem;
/* Private constructor, so only the friends above can create this! */
TreeViewItemContainer() = default;
protected:
Vector<std::unique_ptr<AbstractTreeViewItem>> children_;
/** Adding the first item to the root will set this, then it's passed on to all children. */
TreeViewItemContainer *root_ = nullptr;
/** Pointer back to the owning item. */
AbstractTreeViewItem *parent_ = nullptr;
/**
* Can be set to true to indicate that all of the children items do not have children themselves.
* In this case, no space is reserved for the chevron.
*/
bool is_flat_ = false;
public:
enum class IterOptions {
None = 0,
SkipCollapsed = 1 << 0,
SkipFiltered = 1 << 1,
};
using ItemIterFn = FunctionRef<void(AbstractTreeViewItem &)>;
/**
* Convenience wrapper constructing the item by forwarding given arguments to the constructor of
* the type (\a ItemT).
*
* E.g. if your tree-item type has the following constructor:
* \code{.cpp}
* MyTreeItem(std::string str, int i);
* \endcode
* You can add an item like this:
* \code
* add_tree_item<MyTreeItem>("blabla", 42);
* \endcode
*/
template<class ItemT, typename... Args> inline ItemT &add_tree_item(Args &&...args);
/**
* Add an already constructed tree item to this parent. Ownership is moved to it.
* All tree items must be added through this, it handles important invariants!
*/
AbstractTreeViewItem &add_tree_item(std::unique_ptr<AbstractTreeViewItem> item);
protected:
void foreach_item_recursive(ItemIterFn iter_fn, IterOptions options = IterOptions::None) const;
void foreach_parent(ItemIterFn iter_fn) const;
void sort_alpha();
/* Sort tree item list in reverse order. */
void foreach_sort_invert(TreeViewSortOrder order);
};
ENUM_OPERATORS(TreeViewItemContainer::IterOptions);
/**
* The container class is the base for both the tree-view and the items. This alias gives it a
* clearer name for handles that accept both. Use whenever something wants to act on child-items,
* irrespective of if they are stored at root level or as children of some other item.
*/
using TreeViewOrItem = TreeViewItemContainer;
/** \} */
/* ---------------------------------------------------------------------- */
/** \name Tree-View Base Class
* \{ */
class AbstractTreeView : public AbstractView, public TreeViewItemContainer {
/* Shared pointer so the pointer can be kept persistent over redraws. The grip button gets a
* pointer to modify the value on resizing, and it uses it to identify the button over redraws.
*/
/* TODO support region zoom. */
std::shared_ptr<int> custom_height_ = nullptr;
/** Scroll offset in items, also see #uiViewState.scroll_offset. Clamped before creating the
* button layout. */
std::shared_ptr<int> scroll_value_ = nullptr;
/**
* The total number of items in the tree during the last redraw.
*/
int last_tot_items_ = 0;
bool scroll_active_into_view_on_draw_ = false;
/**
* Collapse/expand state of filter panel.
*/
std::shared_ptr<char> show_display_options_ = std::make_shared<char>(0);
/**
* When true, show elements that doesn't match with the search string.
*/
std::shared_ptr<char> invert_search_filter_ = std::make_shared<char>(0);
/* `char[UI_MAX_NAME_STR]` wrapped in shared pointer, to keep a stable pointer over
* reconstruction that can be passed to buttons. */
std::shared_ptr<char[]> search_string_{new char[256 /*UI_MAX_NAME_STR*/]{}};
/**
* When true, sort elements alphabetically.
*/
std::shared_ptr<char> sort_alpha_ = std::make_shared<char>(0);
/**
* Invert sort order.
*/
std::shared_ptr<TreeViewSortOrder> invert_sort_type_ = std::make_shared<TreeViewSortOrder>(
TreeViewSortOrder::None);
friend class AbstractTreeViewItem;
friend class TreeViewBuilder;
friend class TreeViewLayoutBuilder;
friend class TreeViewItemDropTarget;
public:
/* virtual */ ~AbstractTreeView() override = default;
void draw_overlays(const ARegion &region, const Block &block) const override;
void foreach_item(ItemIterFn iter_fn, IterOptions options = IterOptions::None) const;
void foreach_root_item(ItemIterFn iter_fn) const;
bool is_fully_visible() const override;
void scroll(ViewScrollDirection direction) override;
/** Visual feature: Define a number of item rows the view will show by default. If there
* are fewer items, empty dummy items will be added. These contribute to the view bounds, so the
* drop target of the view includes them, but they are not interactive (e.g. no mouse-hover
* highlight).
*
* \note Value should be greater than #MIN_ROWS. This is to prevent resizing below certain
* height. */
void set_default_rows(int default_rows);
TreeViewSortOrder invert_sort_type_get() const;
/**
* Scroll the view so the active item is visible.
*/
void scroll_active_into_view(bContext *C, bool scroll_active_to_center = false) override;
protected:
virtual void build_tree() = 0;
std::optional<uiViewState> persistent_state() const override;
void persistent_state_apply(const uiViewState &state) override;
private:
void foreach_view_item(FunctionRef<void(AbstractViewItem &)> iter_fn) const final;
void update_children_from_old(const AbstractView &old_view) override;
static void update_children_from_old_recursive(const TreeViewOrItem &new_items,
const TreeViewOrItem &old_items);
static AbstractTreeViewItem *find_matching_child(
const AbstractTreeViewItem &lookup_item, const Span<AbstractTreeViewItem *> possible_items);
std::optional<int> tot_visible_row_count() const;
bool supports_scrolling() const override;
void draw_hierarchy_lines(const ARegion &region, const Block &block) const;
void get_hierarchy_lines(const ARegion &region,
const TreeViewOrItem &parent,
const float aspect,
Vector<std::pair<int2, int2>> &lines,
int &visible_item_index) const;
int count_visible_descendants(const AbstractTreeViewItem &parent) const;
void sort_inverted();
AbstractViewItem *find_active_or_visible_item() const override;
AbstractViewItem *navigate_left(AbstractViewItem *from) override;
AbstractViewItem *navigate_right(AbstractViewItem *from) override;
AbstractViewItem *navigate_up(AbstractViewItem *from) override;
AbstractViewItem *navigate_down(AbstractViewItem *from) override;
};
/** \} */
/* ---------------------------------------------------------------------- */
/** \name Tree-View Item Type
* \{ */
/** \brief Abstract base class for defining a customizable tree-view item.
*
* The tree-view item defines how to build its data into a tree-row. There are implementations for
* common layouts, e.g. #BasicTreeViewItem.
* It also stores state information that needs to be persistent over redraws, like the collapsed
* state.
*/
class AbstractTreeViewItem : public AbstractViewItem, public TreeViewItemContainer {
friend class AbstractTreeView;
friend class TreeViewLayoutBuilder;
/* Higher-level API. */
friend class TreeViewItemAPIWrapper;
private:
bool is_open_ = false;
protected:
/** This label is used as the default way to identifying an item within its parent. */
std::string label_;
public:
AbstractTreeViewItem();
/* virtual */ ~AbstractTreeViewItem() override = default;
virtual void build_row(Layout &row) = 0;
/* virtual */ std::optional<std::string> debug_name() const override;
std::unique_ptr<DropTargetInterface> create_item_drop_target() final;
virtual std::unique_ptr<TreeViewItemDropTarget> create_drop_target();
AbstractTreeView &get_tree_view() const;
/**
* Calculate the view item rectangle from its view-item button, converted to window space.
* Returns an unset optional if there is no view item button for this item.
*/
std::optional<rctf> get_win_rect(const ARegion &region) const;
void begin_renaming();
/**
* Toggle the expanded/collapsed state.
*
* \note this does not call #on_collapse_change().
* \returns true when the collapsed state was changed, false otherwise.
*/
bool toggle_collapsed();
/**
* Expand or collapse this tree view item.
*
* \note this does not call #on_collapse_change().
* \returns true when the collapsed state was changed, false otherwise.
*/
virtual bool set_collapsed(bool collapsed);
/**
* Called when the view changes an item's state from expanded to collapsed, or vice versa. Will
* only be called if the state change is triggered through the view, not through external
* changes. E.g. a click on an item calls it, a change in the value returned by
* #should_be_collapsed() to reflect an external state change does not.
*/
virtual void on_collapse_change(bContext &C, bool is_collapsed);
/**
* If the result is not empty, it controls whether the item should be collapsed or not, usually
* depending on the data that the view represents.
*/
virtual std::optional<bool> should_be_collapsed() const;
/**
* Make this item be uncollapsed on first draw (may later be overridden by
* #should_be_collapsed()). Must only be done during tree building.
*
* \note this does not call #on_collapse_change() or #set_collapsed() overrides.
*/
void uncollapse_by_default();
/**
* Requires the tree to have completed reconstruction, see #is_reconstructed(). Otherwise we
* can't be sure about the item state.
*/
bool is_collapsed() const;
bool is_collapsible() const;
int count_parents() const;
AbstractTreeViewItem *get_parent();
/* Return first child view item. */
AbstractTreeViewItem *get_child();
void on_filter() override;
StringRefNull label() const;
protected:
/** See AbstractViewItem::get_rename_string(). */
/* virtual */ StringRef get_rename_string() const override;
/** See AbstractViewItem::rename(). */
/* virtual */ bool rename(const bContext &C, StringRefNull new_name) override;
/**
* Return whether the item can be collapsed. Used to disable collapsing for items with children.
* The default implementation returns true.
*/
virtual bool supports_collapsing() const;
/**
* Toggle the collapsed/expanded state, and call on_collapse_change() if it changed.
*/
void toggle_collapsed_from_view(bContext &C);
void change_state_delayed() override;
/** See #AbstractViewItem::matches(). */
/* virtual */ bool matches(const AbstractViewItem &other) const override;
/** See #AbstractViewItem::update_from_old(). */
/* virtual */ void update_from_old(const AbstractViewItem &old) override;
bool should_be_filtered_visible(StringRefNull filter_string) const override;
/**
* Compare this item to \a other to check if they represent the same data.
* Used to recognize an item from a previous redraw, to be able to keep its state (e.g.
* open/closed, active, etc.). Items are only matched if their parents also match.
* By default this just matches the item's label (if the parents match!). If that isn't
* good enough for a sub-class, that can override it.
*
* TODO #matches_single() is a rather temporary name, used to indicate that this only compares
* the item itself, not the parents. Item matching is expected to change quite a bit anyway.
*/
virtual bool matches_single(const AbstractTreeViewItem &other) const;
void ensure_parents_uncollapsed();
private:
static void collapse_chevron_click_fn(bContext *, void *but_arg1, void *);
/**
* Override of #AbstractViewItem::set_state_active() that also ensures the parents of this
* element are uncollapsed so that the item is visible.
*/
bool set_state_active() final;
void add_treerow_button(Block &block);
int indent_width() const;
void add_indent(Layout &row) const;
void add_collapse_chevron(Block &block) const;
void add_rename_button(Layout &row);
bool has_active_child() const;
};
/** \} */
/* ---------------------------------------------------------------------- */
/** \name Predefined Tree-View Item Types
*
* Common, Basic Tree-View Item Types.
* \{ */
/**
* The most basic type, just a label with an icon.
*/
class BasicTreeViewItem : public AbstractTreeViewItem {
public:
using IsActiveFn = std::function<bool()>;
using ActivateFn = std::function<void(bContext &C, BasicTreeViewItem &new_active)>;
BIFIconID icon;
explicit BasicTreeViewItem(StringRef label, BIFIconID icon = ICON_NONE);
void build_row(Layout &row) override;
void add_label(Layout &layout, StringRefNull label_override = "");
void set_on_activate_fn(ActivateFn fn);
/**
* Set a custom callback to check if this item should be active.
*/
void set_is_active_fn(IsActiveFn is_active_fn);
protected:
/**
* Called when activating this tree view item. This way users don't have to sub-class
* #BasicTreeViewItem, just to implement custom activation behavior (a common thing to do).
*/
ActivateFn activate_fn_;
IsActiveFn is_active_fn_;
private:
std::optional<bool> should_be_active() const override;
void on_activate(bContext &C) override;
};
/** \} */
/* ---------------------------------------------------------------------- */
/** \name Drag & Drop
* \{ */
/**
* Class to define the behavior when dropping something onto/into a view item, plus the behavior
* when dragging over this item. An item can return a drop target for itself via a custom
* implementation of #AbstractTreeViewItem::create_drop_target().
*
* By default the drop target only supports dropping into/onto itself. To support
* inserting/reordering behavior, where dropping before or after the drop-target is supported, pass
* a different #DropBehavior to the constructor.
*/
class TreeViewItemDropTarget : public DropTargetInterface {
protected:
AbstractTreeViewItem &view_item_;
const DropBehavior behavior_;
public:
TreeViewItemDropTarget(AbstractTreeViewItem &view_item,
DropBehavior behavior = DropBehavior::Insert);
std::optional<DropLocation> choose_drop_location(const ARegion &region,
const wmEvent &event) const override;
/** Request the view the item is registered for as type #ViewType. Throws a `std::bad_cast`
* exception if the view is not of the requested type. */
template<class ViewType> inline ViewType &get_view() const;
};
/** \} */
/* ---------------------------------------------------------------------- */
/** \name Tree-View Builder
* \{ */
class TreeViewBuilder {
public:
static void build_tree_view(const bContext &C,
AbstractTreeView &tree_view,
Layout &layout,
bool add_box = true);
private:
static void ensure_min_rows_items(AbstractTreeView &tree_view);
};
/** \} */
/* ---------------------------------------------------------------------- */
template<class ItemT, typename... Args>
inline ItemT &TreeViewItemContainer::add_tree_item(Args &&...args)
{
static_assert(std::is_base_of_v<AbstractTreeViewItem, ItemT>,
"Type must derive from and implement the AbstractTreeViewItem interface");
return dynamic_cast<ItemT &>(
add_tree_item(std::make_unique<ItemT>(std::forward<Args>(args)...)));
}
template<class ViewType> ViewType &TreeViewItemDropTarget::get_view() const
{
static_assert(std::is_base_of_v<AbstractTreeView, ViewType>,
"Type must derive from and implement the ui::AbstractTreeView interface");
return dynamic_cast<ViewType &>(view_item_.get_tree_view());
}
} // namespace ui
} // namespace blender

View File

@@ -0,0 +1,612 @@
/* SPDX-FileCopyrightText: 2008 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup editorui
* Generic 2D view with should allow drawing grids,
* panning, zooming, scrolling, .. etc.
*/
#pragma once
#include "BLI_compiler_attrs.h"
#include "BLI_rect.h"
namespace blender {
/* -------------------------------------------------------------------- */
/** \name Forward Declarations
* \{ */
struct View2D;
struct ARegion;
struct Scene;
struct ScrArea;
struct bContext;
struct bScreen;
struct rctf;
struct rcti;
struct wmEvent;
struct wmGizmoGroupType;
struct wmKeyConfig;
struct wmOperator;
struct wmOperatorType;
/** \} */
namespace ui {
/* -------------------------------------------------------------------- */
/** \name General Defines
* \{ */
/** Generic value to use when coordinate lies out of view when converting. */
#define V2D_IS_CLIPPED 12000
/**
* Common View2D view types.
*
* \note only define a type here if it completely sets all (+/- a few) of the relevant flags and
* settings for a View2D region, and that set of settings is used in more than one specific place.
*/
enum eView2D_CommonViewTypes {
/** custom view type (region has defined all necessary flags already). */
V2D_COMMONVIEW_CUSTOM = -1,
/** standard (only use this when setting up a new view, as a sensible base for most settings). */
V2D_COMMONVIEW_STANDARD,
/** List-view (i.e. Outliner). */
V2D_COMMONVIEW_LIST,
/** Stack-view (this is basically a list where new items are added at the top). */
V2D_COMMONVIEW_STACK,
/** headers (this is basically the same as list-view, but no Y-panning). */
V2D_COMMONVIEW_HEADER,
/** UI region containing panels. */
V2D_COMMONVIEW_PANELS_UI,
};
/** \} */
/* -------------------------------------------------------------------- */
/** \name Defines for Scroll Bars
* \{ */
/** Scroll bar area. */
/* Maximum has to include outline which varies with line width. */
#define V2D_SCROLL_HEIGHT ((0.45f * U.widget_unit) + (2.0f * U.pixelsize))
#define V2D_SCROLL_WIDTH ((0.45f * U.widget_unit) + (2.0f * U.pixelsize))
/* Alpha of scroll-bar when at minimum size. */
#define V2D_SCROLL_MIN_ALPHA (0.4f)
/* Minimum size needs to include outline which varies with line width. */
#define V2D_SCROLL_MIN_WIDTH ((5.0f * UI_SCALE_FAC) + (2.0f * U.pixelsize))
/* When to start showing the full-width scroller. */
#define V2D_SCROLL_HIDE_WIDTH (AREAMINX * UI_SCALE_FAC)
#define V2D_SCROLL_HIDE_HEIGHT (HEADERY * UI_SCALE_FAC)
/** Scroll bars with 'handles' used for scale (zoom). */
#define V2D_SCROLL_HANDLE_HEIGHT (0.6f * U.widget_unit)
#define V2D_SCROLL_HANDLE_WIDTH (0.6f * U.widget_unit)
/** Scroll bar with 'handles' hot-spot radius for cursor proximity. */
#define V2D_SCROLL_HANDLE_SIZE_HOTSPOT (0.6f * U.widget_unit)
/** Don't allow scroll thumb to show below this size (so it's never too small to click on). */
#define V2D_SCROLL_THUMB_SIZE_MIN (30.0 * UI_SCALE_FAC)
/** \} */
/* -------------------------------------------------------------------- */
/** \name Define for #view2d_sync
* \{ */
/* means copy it from another v2d */
#define V2D_LOCK_SET 0
/* means copy it to the other v2ds */
#define V2D_LOCK_COPY 1
/** \} */
/* -------------------------------------------------------------------- */
/** \name Macros
* \{ */
/* Test if mouse in a scroll-bar (assume that scroller availability has been tested). */
#define IN_2D_VERT_SCROLL(v2d, co) (BLI_rcti_isect_pt_v(&v2d->vert, co))
#define IN_2D_HORIZ_SCROLL(v2d, co) (BLI_rcti_isect_pt_v(&v2d->hor, co))
#define IN_2D_VERT_SCROLL_RECT(v2d, rct) (BLI_rcti_isect(&v2d->vert, rct, NULL))
#define IN_2D_HORIZ_SCROLL_RECT(v2d, rct) (BLI_rcti_isect(&v2d->hor, rct, NULL))
/** \} */
/* -------------------------------------------------------------------- */
/** \name Prototypes
* \{ */
/**
* Refresh and validation (of view rects).
*
* Initialize all relevant View2D data (including view rects if first time)
* and/or refresh mask sizes after view resize.
*
* - For some of these presets, it is expected that the region will have defined some
* additional settings necessary for the customization of the 2D viewport to its requirements
* - This function should only be called from region init() callbacks, where it is expected that
* this is called before #view2d_size_update(),
* as this one checks that the rects are properly initialized.
*/
void view2d_region_reinit(View2D *v2d, short type, int winx, int winy);
void view2d_curRect_validate(View2D *v2d);
/**
* Restore 'cur' rect to standard orientation (i.e. optimal maximum view of tot).
* This does not take into account if zooming the view on an axis
* will improve the view (if allowed).
*/
void view2d_curRect_reset(View2D *v2d);
bool view2d_area_supports_sync(ScrArea *area);
/**
* Called by menus to activate it, or by view2d operators
* to make sure 'related' views stay in synchrony.
*/
void view2d_sync(bScreen *screen, ScrArea *area, View2D *v2dcur, int flag);
/**
* Perform all required updates after `v2d->cur` as been modified.
* This includes like validation view validation (#view2d_curRect_validate).
*
* Current intent is to use it from user code, such as view navigation and zoom operations.
*/
void view2d_curRect_changed(const bContext *C, View2D *v2d);
void view2d_totRect_set(View2D *v2d, int width, int height);
void view2d_mask_from_win(const View2D *v2d, rcti *r_mask);
void view2d_zoom_cache_reset();
/**
* Clamp view2d area to what's visible, preventing
* scrolling vertically to infinity.
*/
void view2d_curRect_clamp_y(View2D *v2d);
/** \} */
/* -------------------------------------------------------------------- */
/** \name View Matrix Operations
* \{ */
/**
* Set view matrices to use 'cur' rect as viewing frame for View2D drawing.
*/
void view2d_view_ortho(const View2D *v2d);
/**
* Set view matrices to only use one axis of 'cur' only
*
* \param xaxis: if non-zero, only use cur x-axis,
* otherwise use cur-yaxis (mostly this will be used for x).
*/
void view2d_view_orthoSpecial(ARegion *region, View2D *v2d, bool xaxis);
/**
* Restore view matrices after drawing.
*/
void view2d_view_restore(const bContext *C);
/** \} */
/* -------------------------------------------------------------------- */
/** \name Grid Drawing
* \{ */
/**
* Draw a multi-level grid in given 2d-region.
*/
void view2d_multi_grid_draw(
const View2D *v2d, int colorid, float step, int level_size, int totlevels);
/**
* Draw a multi-level grid of dots, with a dynamic number of levels based on the fading.
*
* \param grid_color_id: The theme color used for the points. Faded dynamically based on zoom.
* \param min_step: The base size of the grid. At different zoom levels, the visible grid may have
* a larger step size.
* \param grid_subdivisions: The maximum number of sub-levels drawn at once.
*/
void view2d_dot_grid_draw(const View2D *v2d,
int grid_color_id,
float min_step,
int grid_subdivisions);
/**
* Draw horizontal lines.
*
* \param base: Defines in what distance the lines are drawn. Depending on the zoom level of the
* `v2d` the distance is always a full fraction or multiple of the given base.
*/
void view2d_draw_lines_y(const View2D *v2d, bool show_fractions, int base);
/**
* Draw vertical lines. Where lines are drawn is determined by the zoom factor and `base`.
*
* \param show_fractions: If true, lines will be drawn between full values too.
* \param draw_minor_lines: If true, draw extra lines with less visual weight to further break down
* the view area.
* \param base: Defines in what distance the lines are drawn. Depending on the zoom level of the
* `v2d` the distance is always a full fraction or multiple of the given base.
*/
void view2d_draw_lines_x(const View2D *v2d,
const Scene *scene,
bool display_seconds,
bool show_fractions,
bool draw_minor_lines,
int base);
/**
* Wrapper around `view2d_draw_lines_x` that calculates the `base` from the `scene` frame-rate.
*/
void view2d_draw_lines_x_frames(const View2D *v2d,
const Scene *scene,
bool display_seconds,
bool show_fractions,
bool draw_minor_lines);
float view2d_grid_resolution_x(const View2D *v2d, const Scene *scene, bool display_seconds);
float view2d_grid_resolution_y__values(const View2D *v2d, int base);
/**
* Scale indicator text drawing.
*/
void view2d_draw_scale_y(
const ARegion *region, const View2D *v2d, const rcti *rect, int colorid, int base);
/**
* Draw a text scale in either frames or seconds.
*
* \param display_seconds: If true, the scale is interpreted as seconds and will draw a time-code.
* \param show_fractions: If true, fractional scales will be drawn when zoomed in far enough.
* Otherwise the minimum step distance is clamped to 1, meaning only whole number indicators will
* be drawn even when zoomed in. If `display_seconds` is true, this setting will always be false.
* \param base: Defines in what distance the numbers are drawn. Depending on the zoom level of the
* `v2d` the distance is always a full fraction or multiple of the given base.
*/
void view2d_draw_scale_x(const ARegion *region,
const View2D *v2d,
const rcti *rect,
const Scene *scene,
bool display_seconds,
bool show_fractions,
int colorid,
int base);
/** \} */
/* -------------------------------------------------------------------- */
/** \name Scroll-bar Drawing
* \{ */
/**
* Draw scroll-bars in the given 2D-region.
*/
void view2d_scrollers_draw(View2D *v2d, const rcti *mask_custom);
/** \} */
/* -------------------------------------------------------------------- */
/** \name List View Tools
* \{ */
/**
* Get the 'cell' (row, column) that the given 2D-view coordinates
* (i.e. in 'tot' rect space) lie in.
*
* \param columnwidth, rowheight: size of each 'cell'
* \param startx, starty: coordinates (in 'tot' rect space) that the list starts from.
* This should be (0,0) for most views. However, for those where the starting row was offset
* (like for Animation Editor channel lists, to make the first entry more visible), these will be
* the min-coordinates of the first item.
* \param viewx, viewy: 2D-coordinates (in 2D-view / 'tot' rect space) to get the cell for
* \param r_column, r_row: The 'coordinates' of the relevant 'cell'.
*/
void view2d_listview_view_to_cell(float columnwidth,
float rowheight,
float startx,
float starty,
float viewx,
float viewy,
int *r_column,
int *r_row);
/** \} */
/* -------------------------------------------------------------------- */
/** \name Coordinate Conversion
* \{ */
float view2d_region_to_view_x(const View2D *v2d, float x);
float view2d_region_to_view_y(const View2D *v2d, float y);
/**
* Convert from screen/region space to 2d-View space
*
* \param x, y: coordinates to convert
* \param r_view_x, r_view_y: resultant coordinates
*/
void view2d_region_to_view(const View2D *v2d, float x, float y, float *r_view_x, float *r_view_y)
ATTR_NONNULL();
void view2d_region_to_view_rctf(const View2D *v2d, const rctf *rect_src, rctf *rect_dst)
ATTR_NONNULL();
float view2d_view_to_region_x(const View2D *v2d, float x);
float view2d_view_to_region_y(const View2D *v2d, float y);
/**
* Convert from 2d-View space to screen/region space
* \note Coordinates are clamped to lie within bounds of region
*
* \param x, y: Coordinates to convert.
* \param r_region_x, r_region_y: Resultant coordinates.
*/
bool view2d_view_to_region_clip(
const View2D *v2d, float x, float y, int *r_region_x, int *r_region_y) ATTR_NONNULL();
bool view2d_view_to_region_segment_clip(const View2D *v2d,
const float xy_a[2],
const float xy_b[2],
int r_region_a[2],
int r_region_b[2]) ATTR_NONNULL();
/**
* Convert from 2d-view space to screen/region space
*
* \note Coordinates are NOT clamped to lie within bounds of region.
*
* \param x, y: Coordinates to convert.
* \param r_region_x, r_region_y: Resultant coordinates.
*/
void view2d_view_to_region(const View2D *v2d, float x, float y, int *r_region_x, int *r_region_y)
ATTR_NONNULL();
void view2d_view_to_region_fl(
const View2D *v2d, float x, float y, float *r_region_x, float *r_region_y) ATTR_NONNULL();
void view2d_view_to_region_m4(const View2D *v2d, float matrix[4][4]) ATTR_NONNULL();
void view2d_view_to_region_rcti(const View2D *v2d, const rctf *rect_src, rcti *rect_dst)
ATTR_NONNULL();
bool view2d_view_to_region_rcti_clip(const View2D *v2d, const rctf *rect_src, rcti *rect_dst)
ATTR_NONNULL();
/** \} */
/* -------------------------------------------------------------------- */
/** \name Utilities
* \{ */
/**
* View2D data by default resides in region, so get from region stored in context.
*/
View2D *view2d_fromcontext(const bContext *C);
/**
* Same as #view2d_fromcontext, but it returns region-window.
* Utility for pull-downs or buttons.
*/
View2D *view2d_fromcontext_rwin(const bContext *C);
/**
* Get scroll-bar sizes of the current 2D view.
* The size will be zero if the view has its scroll-bars disabled.
*
* \param mapped: whether to use view2d_scroll_mapped which changes flags
*/
void view2d_scroller_size_get(const View2D *v2d, bool mapped, float *r_x, float *r_y);
/**
* Calculate the scale per-axis of the drawing-area
*
* Is used to inverse correct drawing of icons, etc. that need to follow view
* but not be affected by scale
*
* \param r_x, r_y: scale on each axis
*/
void view2d_scale_get(const View2D *v2d, float *r_x, float *r_y);
float view2d_scale_get_x(const View2D *v2d);
float view2d_scale_get_y(const View2D *v2d);
/**
* Same as `view2d_scale_get() - 1.0f / x, y`.
*/
void view2d_scale_get_inverse(const View2D *v2d, float *r_x, float *r_y);
/**
* Simple functions for consistent center offset access.
* Used by node editor to shift view center for each individual node tree.
*/
void view2d_center_get(const View2D *v2d, float *r_x, float *r_y);
void view2d_center_set(View2D *v2d, float x, float y);
void view2d_size_x_set(View2D *v2d, float size_x);
/**
* Simple pan function
* (0.0, 0.0) bottom left
* (0.5, 0.5) center
* (1.0, 1.0) top right.
*/
void view2d_offset(View2D *v2d, float xfac, float yfac);
/**
* Scrolls the view so that the upper edge is at a multiple of the page size.
*/
void view2d_offset_y_snap_to_closest_page(View2D *v2d);
/**
* Check if mouse is within scrollers
*
* \param xy: Mouse coordinates in screen (not region) space.
* \param r_scroll: Return argument for the mapped view2d scroll flag.
*
* \return appropriate code for match.
* - 'h' = in horizontal scroller.
* - 'v' = in vertical scroller.
* - 0 = not in scroller.
*/
char view2d_mouse_in_scrollers_ex(const ARegion *region,
const View2D *v2d,
const int xy[2],
int *r_scroll) ATTR_NONNULL(1, 2, 3, 4);
char view2d_mouse_in_scrollers(const ARegion *region, const View2D *v2d, const int xy[2])
ATTR_NONNULL(1, 2, 3);
char view2d_rect_in_scrollers_ex(const ARegion *region,
const View2D *v2d,
const rcti *rect,
int *r_scroll) ATTR_NONNULL(1, 2, 3);
char view2d_rect_in_scrollers(const ARegion *region, const View2D *v2d, const rcti *rect)
ATTR_NONNULL(1, 2, 3);
/**
* Cached text drawing in v2d, to allow pixel-aligned draw as post process.
*/
void view2d_text_cache_add(
View2D *v2d, float x, float y, const char *str, size_t str_len, const unsigned char col[4]);
/**
* No clip (yet).
*/
void view2d_text_cache_add_rectf(View2D *v2d,
const rctf *rect_view,
const char *str,
size_t str_len,
const unsigned char col[4]);
void view2d_text_cache_draw(ARegion *region);
/** \} */
/* -------------------------------------------------------------------- */
/** \name Operators
* \{ */
void ED_operatortypes_view2d();
void ED_keymap_view2d(wmKeyConfig *keyconf);
/**
* Will start timer if appropriate.
* the arguments are the desired situation.
*/
void view2d_smooth_view(const bContext *C, ARegion *region, const rctf *cur, int smooth_viewtx);
#define UI_MARKER_MARGIN_Y (34 * UI_SCALE_FAC)
#define UI_TIME_SCRUB_MARGIN_Y (23 * UI_SCALE_FAC)
#define UI_TIME_CACHE_MARGIN_Y (UI_TIME_SCRUB_MARGIN_Y / 6.0f)
#define UI_ANIM_MINY (HEADERY * UI_SCALE_FAC * 1.1f)
#define UI_MARKERS_MINY (HEADERY * UI_SCALE_FAC * 2.0f)
/** \} */
/* -------------------------------------------------------------------- */
/** \name Gizmo Types
* \{ */
/* `view2d_gizmo_navigate.cc` */
/**
* Caller defines the name for gizmo group.
*/
void VIEW2D_GGT_navigate_impl(wmGizmoGroupType *gzgt, const char *idname);
/** \} */
/* -------------------------------------------------------------------- */
/** \name Edge Pan
* \{ */
/**
* Custom-data for view panning operators.
*/
struct View2DEdgePanData {
/** Screen where view pan was initiated. */
bScreen *screen;
/** Area where view pan was initiated. */
ScrArea *area;
/** Region where view pan was initiated. */
ARegion *region;
/** View2d we're operating in. */
View2D *v2d;
/** Limit maximum pannable area. */
struct rctf limit;
/** Panning should only start once being in the inside rect once (e.g. adding nodes can happen
* outside). */
bool enabled;
/** Inside distance in UI units from the edge of the region within which to start panning. */
float inside_pad;
/** Outside distance in UI units from the edge of the region at which to stop panning. */
float outside_pad;
/**
* Width of the zone in UI units where speed increases with distance from the edge.
* At the end of this zone max speed is reached.
*/
float speed_ramp;
/** Maximum speed in UI units per second. */
float max_speed;
/** Delay in seconds before maximum speed is reached. */
float delay;
/**
* Influence factor for view zoom:
* - 0 = Constant speed in UI units.
* - 1 = Constant speed in view space, UI speed slows down when zooming out.
*/
float zoom_influence;
/** Initial view rect. */
rctf initial_rect;
/** Amount to move view relative to zoom. */
float facx, facy;
/* Timers. */
double edge_pan_last_time;
double edge_pan_start_time_x, edge_pan_start_time_y;
};
void view2d_edge_pan_init(bContext *C,
View2DEdgePanData *vpd,
float inside_pad,
float outside_pad,
float speed_ramp,
float max_speed,
float delay,
float zoom_influence);
/**
* Set area which can be panned
*/
void view2d_edge_pan_set_limits(
View2DEdgePanData *vpd, float xmin, float xmax, float ymin, float ymax);
void view2d_edge_pan_reset(View2DEdgePanData *vpd);
/**
* Apply transform to view (i.e. adjust 'cur' rect).
*/
void view2d_edge_pan_apply(bContext *C, View2DEdgePanData *vpd, const int xy[2])
ATTR_NONNULL(1, 2, 3);
/**
* Apply transform to view using mouse events.
*/
void view2d_edge_pan_apply_event(bContext *C, View2DEdgePanData *vpd, const wmEvent *event);
void view2d_edge_pan_cancel(bContext *C, View2DEdgePanData *vpd);
void view2d_edge_pan_operator_properties(wmOperatorType *ot);
void view2d_edge_pan_operator_properties_ex(wmOperatorType *ot,
float inside_pad,
float outside_pad,
float speed_ramp,
float max_speed,
float delay,
float zoom_influence);
/**
* Initialize panning data with operator settings.
*/
void view2d_edge_pan_operator_init(bContext *C, View2DEdgePanData *vpd, wmOperator *op);
/** \} */
} // namespace ui
} // namespace blender