Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Goudey <h.goudey@me.com>2022-01-21 18:38:52 +0300
committerHans Goudey <h.goudey@me.com>2022-01-21 18:38:52 +0300
commit5ad0321cfa644febbd7c2a19dbeaec62d630d59c (patch)
tree0113b02cbff9bd95a7cd669089bca41f9aa7e403 /source/blender
parent3d27612d23f7a8c16d9851c1bd7d70f0d1b6fb1f (diff)
parentc39d514a4eacd4a883775a3fcd8b5a7d8e8e52cc (diff)
Merge branch 'master' into temp-geometry-nodes-extrude-mesh
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/BKE_node.h3
-rw-r--r--source/blender/blenkernel/intern/idprop_serialize.cc2
-rw-r--r--source/blender/blenkernel/intern/node.cc1
-rw-r--r--source/blender/blenloader/intern/versioning_300.c2
-rw-r--r--source/blender/editors/geometry/CMakeLists.txt2
-rw-r--r--source/blender/editors/geometry/geometry_attributes.cc205
-rw-r--r--source/blender/editors/geometry/geometry_intern.hh5
-rw-r--r--source/blender/editors/geometry/geometry_ops.cc3
-rw-r--r--source/blender/editors/interface/interface_template_search_menu.cc3
-rw-r--r--source/blender/gpu/intern/gpu_shader_builtin.c14
-rw-r--r--source/blender/gpu/shaders/infos/gpu_shader_2D_image_rect_color_info.hh2
-rw-r--r--source/blender/gpu/shaders/infos/gpu_shader_3D_flat_color_info.hh1
-rw-r--r--source/blender/gpu/shaders/infos/gpu_shader_3D_point_info.hh2
-rw-r--r--source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc2
-rw-r--r--source/blender/io/wavefront_obj/exporter/obj_export_file_writer.hh6
-rw-r--r--source/blender/io/wavefront_obj/exporter/obj_export_io.hh82
-rw-r--r--source/blender/makesrna/RNA_enum_types.h4
-rw-r--r--source/blender/makesrna/intern/rna_attribute.c9
-rw-r--r--source/blender/makesrna/intern/rna_wm.c2
-rw-r--r--source/blender/nodes/NOD_geometry.h1
-rw-r--r--source/blender/nodes/NOD_static_types.h1
-rw-r--r--source/blender/nodes/geometry/CMakeLists.txt1
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_flip_faces.cc114
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_input_mesh_island.cc62
-rw-r--r--source/blender/windowmanager/wm_event_types.h169
25 files changed, 572 insertions, 126 deletions
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index bf958b0868a..bb7d647e713 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -1630,7 +1630,8 @@ int ntreeTexExecTree(struct bNodeTree *ntree,
#define GEO_NODE_INPUT_MESH_EDGE_ANGLE 1147
#define GEO_NODE_FIELD_AT_INDEX 1148
#define GEO_NODE_CURVE_PRIMITIVE_ARC 1149
-#define GEO_NODE_EXTRUDE_MESH 1150
+#define GEO_NODE_FLIP_FACES 1150
+#define GEO_NODE_EXTRUDE_MESH 1151
/** \} */
diff --git a/source/blender/blenkernel/intern/idprop_serialize.cc b/source/blender/blenkernel/intern/idprop_serialize.cc
index 289bc39f4b5..92dce49500c 100644
--- a/source/blender/blenkernel/intern/idprop_serialize.cc
+++ b/source/blender/blenkernel/intern/idprop_serialize.cc
@@ -29,7 +29,7 @@ using namespace blender::io::serialize;
/* Forward declarations */
class IDPropertySerializer;
-class DictionaryEntryParser;
+struct DictionaryEntryParser;
static IDProperty *idprop_from_value(const DictionaryValue &value);
static const IDPropertySerializer &serializer_for(eIDPropertyType property_type);
static const IDPropertySerializer &serializer_for(StringRef idprop_typename);
diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc
index 6271561ae23..56841368893 100644
--- a/source/blender/blenkernel/intern/node.cc
+++ b/source/blender/blenkernel/intern/node.cc
@@ -4770,6 +4770,7 @@ static void registerGeometryNodes()
register_node_type_geo_edge_split();
register_node_type_geo_extrude_mesh();
register_node_type_geo_field_at_index();
+ register_node_type_geo_flip_faces();
register_node_type_geo_geometry_to_instance();
register_node_type_geo_image_texture();
register_node_type_geo_input_curve_handles();
diff --git a/source/blender/blenloader/intern/versioning_300.c b/source/blender/blenloader/intern/versioning_300.c
index 78ec2276af7..81fc6086951 100644
--- a/source/blender/blenloader/intern/versioning_300.c
+++ b/source/blender/blenloader/intern/versioning_300.c
@@ -2551,6 +2551,8 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
ntree, GEO_NODE_STRING_TO_CURVES, "Curves", "Curve Instances");
version_node_output_socket_name(
ntree, GEO_NODE_INPUT_MESH_EDGE_ANGLE, "Angle", "Unsigned Angle");
+ version_node_output_socket_name(
+ ntree, GEO_NODE_INPUT_MESH_ISLAND, "Index", "Island Index");
version_node_input_socket_name(ntree, GEO_NODE_TRANSFER_ATTRIBUTE, "Target", "Source");
}
}
diff --git a/source/blender/editors/geometry/CMakeLists.txt b/source/blender/editors/geometry/CMakeLists.txt
index 65b9633da98..8c920915937 100644
--- a/source/blender/editors/geometry/CMakeLists.txt
+++ b/source/blender/editors/geometry/CMakeLists.txt
@@ -20,9 +20,11 @@ set(INC
../../blenkernel
../../blenlib
../../depsgraph
+ ../../functions
../../makesdna
../../makesrna
../../windowmanager
+ ../../../../intern/guardedalloc
)
set(INC_SYS
diff --git a/source/blender/editors/geometry/geometry_attributes.cc b/source/blender/editors/geometry/geometry_attributes.cc
index 9c0f6728701..56ecd108bba 100644
--- a/source/blender/editors/geometry/geometry_attributes.cc
+++ b/source/blender/editors/geometry/geometry_attributes.cc
@@ -21,8 +21,18 @@
* \ingroup edgeometry
*/
+#include "MEM_guardedalloc.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_scene_types.h"
+
#include "BKE_attribute.h"
#include "BKE_context.h"
+#include "BKE_deform.h"
+#include "BKE_geometry_set.hh"
+#include "BKE_object_deform.h"
+#include "BKE_report.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -33,10 +43,19 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "UI_interface.h"
+#include "UI_resources.h"
+
#include "ED_object.h"
#include "geometry_intern.hh"
+namespace blender::ed::geometry {
+
+using fn::CPPType;
+using fn::GArray;
+using fn::GVArray;
+
/*********************** Attribute Operators ************************/
static bool geometry_attributes_poll(bContext *C)
@@ -76,7 +95,7 @@ static const EnumPropertyItem *geometry_attribute_domain_itemf(bContext *C,
return DummyRNA_NULL_items;
}
- return rna_enum_attribute_domain_itemf(static_cast<ID *>(ob->data), r_free);
+ return rna_enum_attribute_domain_itemf(static_cast<ID *>(ob->data), false, r_free);
}
static int geometry_attribute_add_exec(bContext *C, wmOperator *op)
@@ -180,3 +199,187 @@ void GEOMETRY_OT_attribute_remove(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+
+enum class ConvertAttributeMode {
+ Generic,
+ UVMap,
+ VertexGroup,
+ VertexColor,
+};
+
+static bool geometry_attribute_convert_poll(bContext *C)
+{
+ if (!geometry_attributes_poll(C)) {
+ return false;
+ }
+
+ Object *ob = ED_object_context(C);
+ ID *data = static_cast<ID *>(ob->data);
+ if (GS(data->name) != ID_ME) {
+ return false;
+ }
+ CustomDataLayer *layer = BKE_id_attributes_active_get(data);
+ if (layer == nullptr) {
+ return false;
+ }
+ return true;
+}
+
+static int geometry_attribute_convert_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = ED_object_context(C);
+ ID *ob_data = static_cast<ID *>(ob->data);
+ CustomDataLayer *layer = BKE_id_attributes_active_get(ob_data);
+ const std::string name = layer->name;
+
+ const ConvertAttributeMode mode = static_cast<ConvertAttributeMode>(
+ RNA_enum_get(op->ptr, "mode"));
+
+ Mesh *mesh = reinterpret_cast<Mesh *>(ob_data);
+ MeshComponent mesh_component;
+ mesh_component.replace(mesh, GeometryOwnershipType::Editable);
+
+ /* General conversion steps are always the same:
+ * 1. Convert old data to right domain and data type.
+ * 2. Copy the data into a new array so that it does not depend on the old attribute anymore.
+ * 3. Delete the old attribute.
+ * 4. Create a new attribute based on the previously copied data. */
+ switch (mode) {
+ case ConvertAttributeMode::Generic: {
+ const AttributeDomain dst_domain = static_cast<AttributeDomain>(
+ RNA_enum_get(op->ptr, "domain"));
+ const CustomDataType dst_type = static_cast<CustomDataType>(
+ RNA_enum_get(op->ptr, "data_type"));
+
+ if (ELEM(dst_type, CD_PROP_STRING, CD_MLOOPCOL)) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot convert to the selected type");
+ return OPERATOR_CANCELLED;
+ }
+
+ GVArray src_varray = mesh_component.attribute_get_for_read(name, dst_domain, dst_type);
+ const CPPType &cpp_type = src_varray.type();
+ void *new_data = MEM_malloc_arrayN(src_varray.size(), cpp_type.size(), __func__);
+ src_varray.materialize_to_uninitialized(new_data);
+ mesh_component.attribute_try_delete(name);
+ mesh_component.attribute_try_create(name, dst_domain, dst_type, AttributeInitMove(new_data));
+ break;
+ }
+ case ConvertAttributeMode::UVMap: {
+ MLoopUV *dst_uvs = static_cast<MLoopUV *>(
+ MEM_calloc_arrayN(mesh->totloop, sizeof(MLoopUV), __func__));
+ VArray<float2> src_varray = mesh_component.attribute_get_for_read<float2>(
+ name, ATTR_DOMAIN_CORNER, {0.0f, 0.0f});
+ for (const int i : IndexRange(mesh->totloop)) {
+ copy_v2_v2(dst_uvs[i].uv, src_varray[i]);
+ }
+ mesh_component.attribute_try_delete(name);
+ CustomData_add_layer_named(
+ &mesh->ldata, CD_MLOOPUV, CD_ASSIGN, dst_uvs, mesh->totloop, name.c_str());
+ break;
+ }
+ case ConvertAttributeMode::VertexColor: {
+ MLoopCol *dst_colors = static_cast<MLoopCol *>(
+ MEM_calloc_arrayN(mesh->totloop, sizeof(MLoopCol), __func__));
+ VArray<ColorGeometry4f> src_varray = mesh_component.attribute_get_for_read<ColorGeometry4f>(
+ name, ATTR_DOMAIN_CORNER, ColorGeometry4f{0.0f, 0.0f, 0.0f, 1.0f});
+ for (const int i : IndexRange(mesh->totloop)) {
+ ColorGeometry4b encoded_color = src_varray[i].encode();
+ copy_v4_v4_uchar(&dst_colors[i].r, &encoded_color.r);
+ }
+ mesh_component.attribute_try_delete(name);
+ CustomData_add_layer_named(
+ &mesh->ldata, CD_MLOOPCOL, CD_ASSIGN, dst_colors, mesh->totloop, name.c_str());
+ break;
+ }
+ case ConvertAttributeMode::VertexGroup: {
+ Array<float> src_weights(mesh->totvert);
+ VArray<float> src_varray = mesh_component.attribute_get_for_read<float>(
+ name, ATTR_DOMAIN_POINT, 0.0f);
+ src_varray.materialize(src_weights);
+ mesh_component.attribute_try_delete(name);
+
+ bDeformGroup *defgroup = BKE_object_defgroup_new(ob, name.c_str());
+ const int defgroup_index = BLI_findindex(BKE_id_defgroup_list_get(&mesh->id), defgroup);
+ MDeformVert *dverts = BKE_object_defgroup_data_create(&mesh->id);
+ for (const int i : IndexRange(mesh->totvert)) {
+ const float weight = src_weights[i];
+ if (weight > 0.0f) {
+ BKE_defvert_add_index_notest(dverts + i, defgroup_index, weight);
+ }
+ }
+ break;
+ }
+ }
+
+ int *active_index = BKE_id_attributes_active_index_p(&mesh->id);
+ if (*active_index > 0) {
+ *active_index -= 1;
+ }
+
+ DEG_id_tag_update(&mesh->id, ID_RECALC_GEOMETRY);
+ WM_main_add_notifier(NC_GEOM | ND_DATA, &mesh->id);
+
+ return OPERATOR_FINISHED;
+}
+
+static void geometry_attribute_convert_ui(bContext *UNUSED(C), wmOperator *op)
+{
+ uiLayout *layout = op->layout;
+
+ uiItemR(layout, op->ptr, "mode", 0, nullptr, ICON_NONE);
+
+ const ConvertAttributeMode mode = static_cast<ConvertAttributeMode>(
+ RNA_enum_get(op->ptr, "mode"));
+
+ if (mode == ConvertAttributeMode::Generic) {
+ uiItemR(layout, op->ptr, "domain", 0, nullptr, ICON_NONE);
+ uiItemR(layout, op->ptr, "data_type", 0, nullptr, ICON_NONE);
+ }
+}
+
+static int geometry_attribute_convert_invoke(bContext *C,
+ wmOperator *op,
+ const wmEvent *UNUSED(event))
+{
+ return WM_operator_props_dialog_popup(C, op, 300);
+}
+
+void GEOMETRY_OT_attribute_convert(wmOperatorType *ot)
+{
+ ot->name = "Convert Attribute";
+ ot->description = "Change how the attribute is stored";
+ ot->idname = "GEOMETRY_OT_attribute_convert";
+
+ ot->invoke = geometry_attribute_convert_invoke;
+ ot->exec = geometry_attribute_convert_exec;
+ ot->poll = geometry_attribute_convert_poll;
+ ot->ui = geometry_attribute_convert_ui;
+
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ static EnumPropertyItem mode_items[] = {
+ {int(ConvertAttributeMode::Generic), "GENERIC", 0, "Generic", ""},
+ {int(ConvertAttributeMode::UVMap), "UV_MAP", 0, "UV Map", ""},
+ {int(ConvertAttributeMode::VertexGroup), "VERTEX_GROUP", 0, "Vertex Group", ""},
+ {int(ConvertAttributeMode::VertexColor), "VERTEX_COLOR", 0, "Vertex Color", ""},
+ {0, nullptr, 0, nullptr, nullptr},
+ };
+
+ PropertyRNA *prop;
+
+ RNA_def_enum(
+ ot->srna, "mode", mode_items, static_cast<int>(ConvertAttributeMode::Generic), "Mode", "");
+
+ prop = RNA_def_enum(ot->srna,
+ "domain",
+ rna_enum_attribute_domain_items,
+ ATTR_DOMAIN_POINT,
+ "Domain",
+ "Which geometry element to move the attribute to");
+ RNA_def_enum_funcs(prop, geometry_attribute_domain_itemf);
+
+ RNA_def_enum(
+ ot->srna, "data_type", rna_enum_attribute_type_items, CD_PROP_FLOAT, "Data Type", "");
+}
+
+} // namespace blender::ed::geometry
diff --git a/source/blender/editors/geometry/geometry_intern.hh b/source/blender/editors/geometry/geometry_intern.hh
index 14992476edd..30a2a1d6eb1 100644
--- a/source/blender/editors/geometry/geometry_intern.hh
+++ b/source/blender/editors/geometry/geometry_intern.hh
@@ -25,6 +25,11 @@
struct wmOperatorType;
+namespace blender::ed::geometry {
+
/* *** geometry_attributes.cc *** */
void GEOMETRY_OT_attribute_add(struct wmOperatorType *ot);
void GEOMETRY_OT_attribute_remove(struct wmOperatorType *ot);
+void GEOMETRY_OT_attribute_convert(struct wmOperatorType *ot);
+
+} // namespace blender::ed::geometry
diff --git a/source/blender/editors/geometry/geometry_ops.cc b/source/blender/editors/geometry/geometry_ops.cc
index ba8afe0e62f..8933b2a7f00 100644
--- a/source/blender/editors/geometry/geometry_ops.cc
+++ b/source/blender/editors/geometry/geometry_ops.cc
@@ -31,6 +31,9 @@
void ED_operatortypes_geometry(void)
{
+ using namespace blender::ed::geometry;
+
WM_operatortype_append(GEOMETRY_OT_attribute_add);
WM_operatortype_append(GEOMETRY_OT_attribute_remove);
+ WM_operatortype_append(GEOMETRY_OT_attribute_convert);
}
diff --git a/source/blender/editors/interface/interface_template_search_menu.cc b/source/blender/editors/interface/interface_template_search_menu.cc
index 7a079e01e61..0ce3a0d8af1 100644
--- a/source/blender/editors/interface/interface_template_search_menu.cc
+++ b/source/blender/editors/interface/interface_template_search_menu.cc
@@ -465,6 +465,9 @@ static MenuSearch_Data *menu_items_from_ui_create(
const char *idname_array[] = {
/* While we could include this, it's just showing filenames to load. */
"TOPBAR_MT_file_open_recent",
+ /* Showing undo history is not helpful since users may accidentally undo
+ * an action they intend to run. */
+ "TOPBAR_MT_undo_history",
};
for (int i = 0; i < ARRAY_SIZE(idname_array); i++) {
MenuType *mt = WM_menutype_find(idname_array[i], false);
diff --git a/source/blender/gpu/intern/gpu_shader_builtin.c b/source/blender/gpu/intern/gpu_shader_builtin.c
index 13f1774df03..9c8dbf8401f 100644
--- a/source/blender/gpu/intern/gpu_shader_builtin.c
+++ b/source/blender/gpu/intern/gpu_shader_builtin.c
@@ -192,8 +192,18 @@ static const GPUShaderStages builtin_shader_stages[GPU_SHADER_BUILTIN_LEN] = {
.create_info = "gpu_shader_2D_flat_color"},
[GPU_SHADER_2D_SMOOTH_COLOR] = {.name = "GPU_SHADER_2D_SMOOTH_COLOR",
.create_info = "gpu_shader_2D_smooth_color"},
- [GPU_SHADER_2D_IMAGE_OVERLAYS_MERGE] = {.name = "GPU_SHADER_2D_IMAGE_OVERLAYS_MERGE",
- .create_info = "gpu_shader_2D_image_overlays_merge"},
+ [GPU_SHADER_2D_IMAGE_OVERLAYS_MERGE] =
+ {
+ .name = "GPU_SHADER_2D_IMAGE_OVERLAYS_MERGE",
+#ifdef __APPLE__
+ /* GPUShaderCreateInfo is disabled on MacOS due to mismatch with OCIO shader. See
+ * T95052 for more details. */
+ .vert = datatoc_gpu_shader_2D_image_vert_glsl,
+ .frag = datatoc_gpu_shader_image_overlays_merge_frag_glsl,
+#else
+ .create_info = "gpu_shader_2D_image_overlays_merge",
+#endif
+ },
[GPU_SHADER_2D_IMAGE_OVERLAYS_STEREO_MERGE] =
{.name = "GPU_SHADER_2D_IMAGE_OVERLAYS_STEREO_MERGE",
.create_info = "gpu_shader_2D_image_overlays_stereo_merge"},
diff --git a/source/blender/gpu/shaders/infos/gpu_shader_2D_image_rect_color_info.hh b/source/blender/gpu/shaders/infos/gpu_shader_2D_image_rect_color_info.hh
index b94556bbb25..4e10b91ef39 100644
--- a/source/blender/gpu/shaders/infos/gpu_shader_2D_image_rect_color_info.hh
+++ b/source/blender/gpu/shaders/infos/gpu_shader_2D_image_rect_color_info.hh
@@ -25,8 +25,6 @@
#include "gpu_shader_create_info.hh"
GPU_SHADER_CREATE_INFO(gpu_shader_2D_image_rect_color)
- .vertex_in(0, Type::VEC2, "pos")
- .vertex_in(1, Type::VEC2, "texCoord")
.vertex_out(smooth_tex_coord_interp_iface)
.fragment_out(0, Type::VEC4, "fragColor")
.push_constant(0, Type::MAT4, "ModelViewProjectionMatrix")
diff --git a/source/blender/gpu/shaders/infos/gpu_shader_3D_flat_color_info.hh b/source/blender/gpu/shaders/infos/gpu_shader_3D_flat_color_info.hh
index 70b2dac8266..14a6986f478 100644
--- a/source/blender/gpu/shaders/infos/gpu_shader_3D_flat_color_info.hh
+++ b/source/blender/gpu/shaders/infos/gpu_shader_3D_flat_color_info.hh
@@ -30,7 +30,6 @@ GPU_SHADER_CREATE_INFO(gpu_shader_3D_flat_color)
.vertex_out(flat_color_iface)
.fragment_out(0, Type::VEC4, "fragColor")
.push_constant(0, Type::MAT4, "ModelViewProjectionMatrix")
- .push_constant(1, Type::BOOL, "srgbTarget")
.vertex_source("gpu_shader_3D_flat_color_vert.glsl")
.fragment_source("gpu_shader_flat_color_frag.glsl")
.additional_info("gpu_srgb_to_framebuffer_space")
diff --git a/source/blender/gpu/shaders/infos/gpu_shader_3D_point_info.hh b/source/blender/gpu/shaders/infos/gpu_shader_3D_point_info.hh
index b62c8fe7518..27357eef8c9 100644
--- a/source/blender/gpu/shaders/infos/gpu_shader_3D_point_info.hh
+++ b/source/blender/gpu/shaders/infos/gpu_shader_3D_point_info.hh
@@ -29,7 +29,6 @@ GPU_SHADER_CREATE_INFO(gpu_shader_3D_point_fixed_size_varying_color)
.vertex_out(smooth_color_iface)
.fragment_out(0, Type::VEC4, "fragColor")
.push_constant(0, Type::MAT4, "ModelViewProjectionMatrix")
- .push_constant(16, Type::FLOAT, "size")
.vertex_source("gpu_shader_3D_point_fixed_size_varying_color_vert.glsl")
.fragment_source("gpu_shader_point_varying_color_frag.glsl")
.do_static_compilation(true);
@@ -52,7 +51,6 @@ GPU_SHADER_CREATE_INFO(gpu_shader_3D_point_uniform_size_uniform_color_aa)
.push_constant(0, Type::MAT4, "ModelViewProjectionMatrix")
.push_constant(16, Type::VEC4, "color")
.push_constant(20, Type::FLOAT, "size")
- .push_constant(24, Type::FLOAT, "outlineWidth")
.vertex_source("gpu_shader_3D_point_uniform_size_aa_vert.glsl")
.fragment_source("gpu_shader_point_uniform_color_aa_frag.glsl")
.do_static_compilation(true);
diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc b/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc
index 8c845c34db2..d31353c4a76 100644
--- a/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc
+++ b/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc
@@ -394,7 +394,7 @@ MTLWriter::MTLWriter(const char *obj_filepath) noexcept(false)
if (!ok) {
throw std::system_error(ENAMETOOLONG, std::system_category(), "");
}
- file_handler_ = std::make_unique<FileHandler<eFileType::MTL>>(mtl_filepath_);
+ file_handler_ = std::make_unique<FormattedFileHandler<eFileType::MTL>>(mtl_filepath_);
}
void MTLWriter::write_header(const char *blen_filepath) const
diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.hh b/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.hh
index 1cad179a70c..7385d9fabe2 100644
--- a/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.hh
+++ b/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.hh
@@ -49,14 +49,14 @@ struct IndexOffsets {
class OBJWriter : NonMovable, NonCopyable {
private:
const OBJExportParams &export_params_;
- std::unique_ptr<FileHandler<eFileType::OBJ>> file_handler_ = nullptr;
+ std::unique_ptr<FormattedFileHandler<eFileType::OBJ>> file_handler_ = nullptr;
IndexOffsets index_offsets_{0, 0, 0};
public:
OBJWriter(const char *filepath, const OBJExportParams &export_params) noexcept(false)
: export_params_(export_params)
{
- file_handler_ = std::make_unique<FileHandler<eFileType::OBJ>>(filepath);
+ file_handler_ = std::make_unique<FormattedFileHandler<eFileType::OBJ>>(filepath);
}
void write_header() const;
@@ -172,7 +172,7 @@ class OBJWriter : NonMovable, NonCopyable {
*/
class MTLWriter : NonMovable, NonCopyable {
private:
- std::unique_ptr<FileHandler<eFileType::MTL>> file_handler_ = nullptr;
+ std::unique_ptr<FormattedFileHandler<eFileType::MTL>> file_handler_ = nullptr;
std::string mtl_filepath_;
Vector<MTLMaterial> mtlmaterials_;
/* Map from a Material* to an index into mtlmaterials_. */
diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_io.hh b/source/blender/io/wavefront_obj/exporter/obj_export_io.hh
index a6f0174d68b..e88a76fc4e8 100644
--- a/source/blender/io/wavefront_obj/exporter/obj_export_io.hh
+++ b/source/blender/io/wavefront_obj/exporter/obj_export_io.hh
@@ -88,6 +88,7 @@ enum class eMTLSyntaxElement {
template<eFileType filetype> struct FileTypeTraits;
+/* Used to prevent mixing of say OBJ file format with MTL syntax elements. */
template<> struct FileTypeTraits<eFileType::OBJ> {
using SyntaxType = eOBJSyntaxElement;
};
@@ -96,15 +97,19 @@ template<> struct FileTypeTraits<eFileType::MTL> {
using SyntaxType = eMTLSyntaxElement;
};
-template<eFileType type> struct Formatting {
+struct FormattingSyntax {
+ /* Formatting syntax with the file format key like `newmtl %s\n`. */
const char *fmt = nullptr;
+ /* Number of arguments needed by the syntax. */
const int total_args = 0;
- /* Fail to compile by default. */
- const bool is_type_valid = false;
+ /* Whether types of the given arguments are accepted by the syntax above. Fail to compile by
+ * default.
+ */
+ const bool are_types_valid = false;
};
/**
- * Type dependent but always false. Use to add a conditional compile-time error.
+ * Type dependent but always false. Use to add a constexpr-conditional compile-time error.
*/
template<typename T> struct always_false : std::false_type {
};
@@ -118,9 +123,8 @@ constexpr bool is_type_integral = (... && std::is_integral_v<std::decay_t<T>>);
template<typename... T>
constexpr bool is_type_string_related = (... && std::is_constructible_v<std::string, T>);
-template<eFileType filetype, typename... T>
-constexpr std::enable_if_t<filetype == eFileType::OBJ, Formatting<filetype>>
-syntax_elem_to_formatting(const eOBJSyntaxElement key)
+template<typename... T>
+constexpr FormattingSyntax syntax_elem_to_formatting(const eOBJSyntaxElement key)
{
switch (key) {
case eOBJSyntaxElement::vertex_coords: {
@@ -201,9 +205,8 @@ syntax_elem_to_formatting(const eOBJSyntaxElement key)
}
}
-template<eFileType filetype, typename... T>
-constexpr std::enable_if_t<filetype == eFileType::MTL, Formatting<filetype>>
-syntax_elem_to_formatting(const eMTLSyntaxElement key)
+template<typename... T>
+constexpr FormattingSyntax syntax_elem_to_formatting(const eMTLSyntaxElement key)
{
switch (key) {
case eMTLSyntaxElement::newmtl: {
@@ -261,21 +264,25 @@ syntax_elem_to_formatting(const eMTLSyntaxElement key)
}
}
-template<eFileType filetype> class FileHandler : NonCopyable, NonMovable {
+/**
+ * File format and syntax agnostic file writer.
+ */
+template<eFileType filetype> class FormattedFileHandler : NonCopyable, NonMovable {
private:
- FILE *outfile_ = nullptr;
+ std::FILE *outfile_ = nullptr;
std::string outfile_path_;
public:
- FileHandler(std::string outfile_path) noexcept(false) : outfile_path_(std::move(outfile_path))
+ FormattedFileHandler(std::string outfile_path) noexcept(false)
+ : outfile_path_(std::move(outfile_path))
{
outfile_ = std::fopen(outfile_path_.c_str(), "w");
if (!outfile_) {
- throw std::system_error(errno, std::system_category(), "Cannot open file");
+ throw std::system_error(errno, std::system_category(), "Cannot open file " + outfile_path_);
}
}
- ~FileHandler()
+ ~FormattedFileHandler()
{
if (outfile_ && std::fclose(outfile_)) {
std::cerr << "Error: could not close the file '" << outfile_path_
@@ -283,17 +290,24 @@ template<eFileType filetype> class FileHandler : NonCopyable, NonMovable {
}
}
+ /**
+ * Example invocation: `writer->write<eMTLSyntaxElement::newmtl>("foo")`.
+ *
+ * \param key Must match what the instance's filetype expects; i.e., `eMTLSyntaxElement` for
+ * `eFileType::MTL`.
+ */
template<typename FileTypeTraits<filetype>::SyntaxType key, typename... T>
constexpr void write(T &&...args) const
{
- constexpr Formatting<filetype> fmt_nargs_valid = syntax_elem_to_formatting<filetype, T...>(
- key);
- write__impl<fmt_nargs_valid.total_args>(fmt_nargs_valid.fmt, std::forward<T>(args)...);
- /* Types of all arguments and the number of arguments should match
- * what the formatting specifies. */
- return std::enable_if_t < fmt_nargs_valid.is_type_valid &&
- (sizeof...(T) == fmt_nargs_valid.total_args),
- void > ();
+ /* Get format syntax, number of arguments expected and whether types of given arguments are
+ * valid.
+ */
+ constexpr FormattingSyntax fmt_nargs_valid = syntax_elem_to_formatting<T...>(key);
+ BLI_STATIC_ASSERT(fmt_nargs_valid.are_types_valid &&
+ (sizeof...(T) == fmt_nargs_valid.total_args),
+ "Types of all arguments and the number of arguments should match what the "
+ "formatting specifies.");
+ write_impl(fmt_nargs_valid.fmt, std::forward<T>(args)...);
}
private:
@@ -301,11 +315,11 @@ template<eFileType filetype> class FileHandler : NonCopyable, NonMovable {
template<typename T> using remove_cvref_t = std::remove_cv_t<std::remove_reference_t<T>>;
/**
- * Make #std::string etc., usable for `fprintf` family.
+ * Make #std::string etc., usable for `fprintf` family. int float etc. are not affected.
* \return: `const char *` or the original argument if the argument is
* not related to #std::string.
*/
- template<typename T> constexpr auto string_to_primitive(T &&arg) const
+ template<typename T> constexpr auto convert_to_primitive(T &&arg) const
{
if constexpr (std::is_same_v<remove_cvref_t<T>, std::string> ||
std::is_same_v<remove_cvref_t<T>, blender::StringRefNull>) {
@@ -319,21 +333,19 @@ template<eFileType filetype> class FileHandler : NonCopyable, NonMovable {
return;
}
else {
+ /* For int, float etc. */
return std::forward<T>(arg);
}
}
- template<int total_args, typename... T>
- constexpr std::enable_if_t<(total_args != 0), void> write__impl(const char *fmt,
- T &&...args) const
- {
- std::fprintf(outfile_, fmt, string_to_primitive(std::forward<T>(args))...);
- }
- template<int total_args, typename... T>
- constexpr std::enable_if_t<(total_args == 0), void> write__impl(const char *fmt,
- T &&...args) const
+ template<typename... T> constexpr void write_impl(const char *fmt, T &&...args) const
{
- std::fputs(fmt, outfile_);
+ if constexpr (sizeof...(T) == 0) {
+ std::fputs(fmt, outfile_);
+ }
+ else {
+ std::fprintf(outfile_, fmt, convert_to_primitive(std::forward<T>(args))...);
+ }
}
};
diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h
index da07f1043a7..fcae1009c8b 100644
--- a/source/blender/makesrna/RNA_enum_types.h
+++ b/source/blender/makesrna/RNA_enum_types.h
@@ -35,7 +35,9 @@ struct bNodeType;
#define DEF_ENUM(id) extern const EnumPropertyItem id[];
#include "RNA_enum_items.h"
-extern const EnumPropertyItem *rna_enum_attribute_domain_itemf(struct ID *id, bool *r_free);
+extern const EnumPropertyItem *rna_enum_attribute_domain_itemf(struct ID *id,
+ bool include_instances,
+ bool *r_free);
/**
* For ID filters (#FILTER_ID_AC, #FILTER_ID_AR, ...) an int isn't enough. This version allows 64
diff --git a/source/blender/makesrna/intern/rna_attribute.c b/source/blender/makesrna/intern/rna_attribute.c
index 78c15444308..35da353a043 100644
--- a/source/blender/makesrna/intern/rna_attribute.c
+++ b/source/blender/makesrna/intern/rna_attribute.c
@@ -166,7 +166,9 @@ static int rna_Attribute_type_get(PointerRNA *ptr)
return layer->type;
}
-const EnumPropertyItem *rna_enum_attribute_domain_itemf(ID *id, bool *r_free)
+const EnumPropertyItem *rna_enum_attribute_domain_itemf(ID *id,
+ bool include_instances,
+ bool *r_free)
{
EnumPropertyItem *item = NULL;
const EnumPropertyItem *domain_item = NULL;
@@ -188,6 +190,9 @@ const EnumPropertyItem *rna_enum_attribute_domain_itemf(ID *id, bool *r_free)
if (id_type == ID_ME && ELEM(domain_item->value, ATTR_DOMAIN_CURVE)) {
continue;
}
+ if (!include_instances && domain_item->value == ATTR_DOMAIN_INSTANCE) {
+ continue;
+ }
if (domain_item->value == ATTR_DOMAIN_POINT && id_type == ID_ME) {
RNA_enum_item_add(&item, &totitem, &mesh_vertex_domain_item);
@@ -207,7 +212,7 @@ static const EnumPropertyItem *rna_Attribute_domain_itemf(bContext *UNUSED(C),
PropertyRNA *UNUSED(prop),
bool *r_free)
{
- return rna_enum_attribute_domain_itemf(ptr->owner_id, r_free);
+ return rna_enum_attribute_domain_itemf(ptr->owner_id, true, r_free);
}
static int rna_Attribute_domain_get(PointerRNA *ptr)
diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c
index 8c128292fd7..c64a47fc2ab 100644
--- a/source/blender/makesrna/intern/rna_wm.c
+++ b/source/blender/makesrna/intern/rna_wm.c
@@ -965,7 +965,7 @@ static void rna_wmKeyMapItem_keymodifier_set(PointerRNA *ptr, int value)
if (value == EVT_ESCKEY) {
/* pass */
}
- else if (value >= EVT_AKEY) {
+ else if (ISKEYBOARD(value) && !ISKEYMODIFIER(value)) {
kmi->keymodifier = value;
}
else {
diff --git a/source/blender/nodes/NOD_geometry.h b/source/blender/nodes/NOD_geometry.h
index 8f6ab1eeb13..0d0e9462891 100644
--- a/source/blender/nodes/NOD_geometry.h
+++ b/source/blender/nodes/NOD_geometry.h
@@ -101,6 +101,7 @@ void register_node_type_geo_dual_mesh(void);
void register_node_type_geo_edge_split(void);
void register_node_type_geo_extrude_mesh(void);
void register_node_type_geo_field_at_index(void);
+void register_node_type_geo_flip_faces(void);
void register_node_type_geo_geometry_to_instance(void);
void register_node_type_geo_image_texture(void);
void register_node_type_geo_input_curve_handles(void);
diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h
index 5c2814e5a33..eae9e5e63ee 100644
--- a/source/blender/nodes/NOD_static_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@ -356,6 +356,7 @@ DefNode(GeometryNode, GEO_NODE_EXTRUDE_MESH, def_geo_extrude_mesh, "EXTRUDE_MESH
DefNode(GeometryNode, GEO_NODE_FIELD_AT_INDEX, def_geo_field_at_index, "FIELD_AT_INDEX", FieldAtIndex, "Field at Index", "")
DefNode(GeometryNode, GEO_NODE_FILL_CURVE, def_geo_curve_fill, "FILL_CURVE", FillCurve, "Fill Curve", "")
DefNode(GeometryNode, GEO_NODE_FILLET_CURVE, def_geo_curve_fillet, "FILLET_CURVE", FilletCurve, "Fillet Curve", "")
+DefNode(GeometryNode, GEO_NODE_FLIP_FACES, 0, "FLIP_FACES", FlipFaces, "Flip Faces", "")
DefNode(GeometryNode, GEO_NODE_GEOMETRY_TO_INSTANCE, 0, "GEOMETRY_TO_INSTANCE", GeometryToInstance, "Geometry to Instance", "")
DefNode(GeometryNode, GEO_NODE_IMAGE_TEXTURE, def_geo_image_texture, "IMAGE_TEXTURE", ImageTexture, "Image Texture", "")
DefNode(GeometryNode, GEO_NODE_INPUT_CURVE_HANDLES, 0, "INPUT_CURVE_HANDLES", InputCurveHandlePositions, "Curve Handle Positions", "")
diff --git a/source/blender/nodes/geometry/CMakeLists.txt b/source/blender/nodes/geometry/CMakeLists.txt
index 6112f358fe9..ab1fefb5ad9 100644
--- a/source/blender/nodes/geometry/CMakeLists.txt
+++ b/source/blender/nodes/geometry/CMakeLists.txt
@@ -119,6 +119,7 @@ set(SRC
nodes/node_geo_edge_split.cc
nodes/node_geo_extrude_mesh.cc
nodes/node_geo_field_at_index.cc
+ nodes/node_geo_flip_faces.cc
nodes/node_geo_geometry_to_instance.cc
nodes/node_geo_image_texture.cc
nodes/node_geo_input_curve_handles.cc
diff --git a/source/blender/nodes/geometry/nodes/node_geo_flip_faces.cc b/source/blender/nodes/geometry/nodes/node_geo_flip_faces.cc
new file mode 100644
index 00000000000..41970d75dfe
--- /dev/null
+++ b/source/blender/nodes/geometry/nodes/node_geo_flip_faces.cc
@@ -0,0 +1,114 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "BKE_mesh.h"
+#include "BKE_mesh_runtime.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+
+#include "BKE_attribute_math.hh"
+
+#include "node_geometry_util.hh"
+
+namespace blender::nodes::node_geo_flip_faces_cc {
+
+static void node_declare(NodeDeclarationBuilder &b)
+{
+ b.add_input<decl::Geometry>(N_("Mesh")).supported_type(GEO_COMPONENT_TYPE_MESH);
+ b.add_input<decl::Bool>(N_("Selection")).default_value(true).hide_value().supports_field();
+ b.add_output<decl::Geometry>(N_("Mesh"));
+}
+
+static void mesh_flip_faces(MeshComponent &component, const Field<bool> &selection_field)
+{
+ GeometryComponentFieldContext field_context{component, ATTR_DOMAIN_FACE};
+ const int domain_size = component.attribute_domain_size(ATTR_DOMAIN_FACE);
+ if (domain_size == 0) {
+ return;
+ }
+ fn::FieldEvaluator evaluator{field_context, domain_size};
+ evaluator.add(selection_field);
+ evaluator.evaluate();
+ const IndexMask selection = evaluator.get_evaluated_as_mask(0);
+
+ Mesh *mesh = component.get_for_write();
+
+ mesh->mloop = (MLoop *)CustomData_duplicate_referenced_layer(
+ &mesh->ldata, CD_MLOOP, mesh->totloop);
+ Span<MPoly> polys{mesh->mpoly, mesh->totpoly};
+ MutableSpan<MLoop> loops{mesh->mloop, mesh->totloop};
+
+ for (const int i : selection.index_range()) {
+ const MPoly &poly = polys[selection[i]];
+ int start = poly.loopstart;
+ for (const int j : IndexRange(poly.totloop / 2)) {
+ const int index1 = start + j + 1;
+ const int index2 = start + poly.totloop - j - 1;
+ std::swap(loops[index1].v, loops[index2].v);
+ std::swap(loops[index1 - 1].e, loops[index2].e);
+ }
+ }
+
+ component.attribute_foreach(
+ [&](const bke::AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) {
+ if (meta_data.domain == ATTR_DOMAIN_CORNER) {
+ OutputAttribute attribute = component.attribute_try_get_for_output(
+ attribute_id, ATTR_DOMAIN_CORNER, meta_data.data_type, nullptr);
+ attribute_math::convert_to_static_type(meta_data.data_type, [&](auto dummy) {
+ using T = decltype(dummy);
+ MutableSpan<T> dst_span = attribute.as_span<T>();
+ for (const int j : selection.index_range()) {
+ const MPoly &poly = polys[selection[j]];
+ dst_span.slice(poly.loopstart + 1, poly.totloop - 1).reverse();
+ }
+ });
+ attribute.save();
+ }
+ return true;
+ });
+}
+
+static void node_geo_exec(GeoNodeExecParams params)
+{
+ GeometrySet geometry_set = params.extract_input<GeometrySet>("Mesh");
+
+ const Field<bool> selection_field = params.extract_input<Field<bool>>("Selection");
+
+ geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
+ if (!geometry_set.has_mesh()) {
+ return;
+ }
+ MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>();
+ mesh_flip_faces(mesh_component, selection_field);
+ });
+
+ params.set_output("Mesh", std::move(geometry_set));
+}
+
+} // namespace blender::nodes::node_geo_flip_faces_cc
+
+void register_node_type_geo_flip_faces()
+{
+ namespace file_ns = blender::nodes::node_geo_flip_faces_cc;
+
+ static bNodeType ntype;
+
+ geo_node_type_base(&ntype, GEO_NODE_FLIP_FACES, "Flip Faces", NODE_CLASS_GEOMETRY);
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.declare = file_ns::node_declare;
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_island.cc b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_island.cc
index 629279a44e9..68bb93bbb64 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_island.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_island.cc
@@ -27,10 +27,13 @@ namespace blender::nodes::node_geo_input_mesh_island_cc {
static void node_declare(NodeDeclarationBuilder &b)
{
- b.add_output<decl::Int>(N_("Index"))
+ b.add_output<decl::Int>(N_("Island Index"))
.field_source()
.description(N_("Island indices are based on the order of the lowest-numbered vertex "
"contained in each island"));
+ b.add_output<decl::Int>(N_("Island Count"))
+ .field_source()
+ .description(N_("The total number of mesh islands"));
}
class IslandFieldInput final : public GeometryFieldInput {
@@ -81,10 +84,63 @@ class IslandFieldInput final : public GeometryFieldInput {
}
};
+class IslandCountFieldInput final : public GeometryFieldInput {
+ public:
+ IslandCountFieldInput() : GeometryFieldInput(CPPType::get<int>(), "Island Count")
+ {
+ category_ = Category::Generated;
+ }
+
+ GVArray get_varray_for_context(const GeometryComponent &component,
+ const AttributeDomain domain,
+ IndexMask UNUSED(mask)) const final
+ {
+ if (component.type() != GEO_COMPONENT_TYPE_MESH) {
+ return {};
+ }
+ const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component);
+ const Mesh *mesh = mesh_component.get_for_read();
+ if (mesh == nullptr) {
+ return {};
+ }
+
+ DisjointSet islands(mesh->totvert);
+ for (const int i : IndexRange(mesh->totedge)) {
+ islands.join(mesh->medge[i].v1, mesh->medge[i].v2);
+ }
+
+ Set<int> island_list;
+ for (const int i_vert : IndexRange(mesh->totvert)) {
+ const int64_t root = islands.find_root(i_vert);
+ island_list.add(root);
+ }
+
+ return VArray<int>::ForSingle(island_list.size(),
+ mesh_component.attribute_domain_size(domain));
+ }
+
+ uint64_t hash() const override
+ {
+ /* Some random hash. */
+ return 45634572457;
+ }
+
+ bool is_equal_to(const fn::FieldNode &other) const override
+ {
+ return dynamic_cast<const IslandCountFieldInput *>(&other) != nullptr;
+ }
+};
+
static void node_geo_exec(GeoNodeExecParams params)
{
- Field<int> island_field{std::make_shared<IslandFieldInput>()};
- params.set_output("Index", std::move(island_field));
+ if (params.output_is_required("Island Index")) {
+ Field<int> field{std::make_shared<IslandFieldInput>()};
+ params.set_output("Island Index", std::move(field));
+ }
+ if (params.output_is_required("Island Count")) {
+ Field<int> field{std::make_shared<IslandCountFieldInput>()};
+ params.set_output("Island Count", std::move(field));
+ }
}
} // namespace blender::nodes::node_geo_input_mesh_island_cc
diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h
index 4ed1b7b9d0d..e58e051c66e 100644
--- a/source/blender/windowmanager/wm_event_types.h
+++ b/source/blender/windowmanager/wm_event_types.h
@@ -29,7 +29,7 @@
extern "C" {
#endif
-/* customdata type */
+/** #wmEvent.customdata type */
enum {
EVT_DATA_TIMER = 2,
EVT_DATA_DRAGDROP = 3,
@@ -37,7 +37,11 @@ enum {
EVT_DATA_XR = 5,
};
-/* tablet active, matches GHOST_TTabletMode */
+/**
+ * #wmTabletData.active tablet active, matches #GHOST_TTabletMode.
+ *
+ * Typically access via `event->tablet.active`.
+ */
enum {
EVT_TABLET_NONE = 0,
EVT_TABLET_STYLUS = 1,
@@ -95,10 +99,14 @@ enum {
TABLET_STYLUS = 0x001a,
TABLET_ERASER = 0x001b,
- /* *** Start of keyboard codes. *** */
+/* *** Start of keyboard codes. *** */
+
+/* Minimum keyboard value (inclusive). */
+#define _EVT_KEYBOARD_MIN 0x0020
/* Standard keyboard.
- * From 0x0020 to 0x00ff, and 0x012c to 0x0143 for function keys! */
+ * - 0x0020 to 0x00ff [#_EVT_KEYBOARD_MIN to #_EVT_KEYBOARD_MAX] inclusive - for keys.
+ * - 0x012c to 0x0143 [#EVT_F1KEY to #EVT_F24KEY] inclusive - for function keys. */
EVT_ZEROKEY = 0x0030, /* '0' (48). */
EVT_ONEKEY = 0x0031, /* '1' (49). */
@@ -210,6 +218,12 @@ enum {
EVT_LEFTBRACKETKEY = 0x00eb, /* 235 */
EVT_RIGHTBRACKETKEY = 0x00ec, /* 236 */
+/* Maximum keyboard value (inclusive). */
+#define _EVT_KEYBOARD_MAX 0x00ff /* 255 */
+
+ /* WARNING: 0x010x are used for internal events
+ * (but are still stored in the key-map). */
+
EVT_F1KEY = 0x012c, /* 300 */
EVT_F2KEY = 0x012d, /* 301 */
EVT_F3KEY = 0x012e, /* 302 */
@@ -237,60 +251,65 @@ enum {
/* *** End of keyboard codes. *** */
- /* NDOF (from SpaceNavigator & friends)
- * These should be kept in sync with GHOST_NDOFManager.h
+ /* NDOF (from "Space Navigator" & friends)
+ * These must be kept in sync with `GHOST_NDOFManager.h`.
* Ordering matters, exact values do not. */
+
NDOF_MOTION = 0x0190, /* 400 */
+
+#define _NDOF_MIN NDOF_MOTION
+
/* used internally, never sent */
NDOF_BUTTON_NONE = NDOF_MOTION,
/* these two are available from any 3Dconnexion device */
- NDOF_BUTTON_MENU,
- NDOF_BUTTON_FIT,
+
+ NDOF_BUTTON_MENU = 0x0191, /* 401 */
+ NDOF_BUTTON_FIT = 0x0192, /* 402 */
/* standard views */
- NDOF_BUTTON_TOP,
- NDOF_BUTTON_BOTTOM,
- NDOF_BUTTON_LEFT,
- NDOF_BUTTON_RIGHT,
- NDOF_BUTTON_FRONT,
- NDOF_BUTTON_BACK,
+ NDOF_BUTTON_TOP = 0x0193, /* 403 */
+ NDOF_BUTTON_BOTTOM = 0x0194, /* 404 */
+ NDOF_BUTTON_LEFT = 0x0195, /* 405 */
+ NDOF_BUTTON_RIGHT = 0x0196, /* 406 */
+ NDOF_BUTTON_FRONT = 0x0197, /* 407 */
+ NDOF_BUTTON_BACK = 0x0198, /* 408 */
/* more views */
- NDOF_BUTTON_ISO1,
- NDOF_BUTTON_ISO2,
+ NDOF_BUTTON_ISO1 = 0x0199, /* 409 */
+ NDOF_BUTTON_ISO2 = 0x019a, /* 410 */
/* 90 degree rotations */
- NDOF_BUTTON_ROLL_CW,
- NDOF_BUTTON_ROLL_CCW,
- NDOF_BUTTON_SPIN_CW,
- NDOF_BUTTON_SPIN_CCW,
- NDOF_BUTTON_TILT_CW,
- NDOF_BUTTON_TILT_CCW,
+ NDOF_BUTTON_ROLL_CW = 0x019b, /* 411 */
+ NDOF_BUTTON_ROLL_CCW = 0x019c, /* 412 */
+ NDOF_BUTTON_SPIN_CW = 0x019d, /* 413 */
+ NDOF_BUTTON_SPIN_CCW = 0x019e, /* 414 */
+ NDOF_BUTTON_TILT_CW = 0x019f, /* 415 */
+ NDOF_BUTTON_TILT_CCW = 0x01a0, /* 416 */
/* device control */
- NDOF_BUTTON_ROTATE,
- NDOF_BUTTON_PANZOOM,
- NDOF_BUTTON_DOMINANT,
- NDOF_BUTTON_PLUS,
- NDOF_BUTTON_MINUS,
+ NDOF_BUTTON_ROTATE = 0x01a1, /* 417 */
+ NDOF_BUTTON_PANZOOM = 0x01a2, /* 418 */
+ NDOF_BUTTON_DOMINANT = 0x01a3, /* 419 */
+ NDOF_BUTTON_PLUS = 0x01a4, /* 420 */
+ NDOF_BUTTON_MINUS = 0x01a5, /* 421 */
/* keyboard emulation */
- NDOF_BUTTON_ESC,
- NDOF_BUTTON_ALT,
- NDOF_BUTTON_SHIFT,
- NDOF_BUTTON_CTRL,
+ NDOF_BUTTON_ESC = 0x01a6, /* 422 */
+ NDOF_BUTTON_ALT = 0x01a7, /* 423 */
+ NDOF_BUTTON_SHIFT = 0x01a8, /* 424 */
+ NDOF_BUTTON_CTRL = 0x01a9, /* 425 */
/* general-purpose buttons */
- NDOF_BUTTON_1,
- NDOF_BUTTON_2,
- NDOF_BUTTON_3,
- NDOF_BUTTON_4,
- NDOF_BUTTON_5,
- NDOF_BUTTON_6,
- NDOF_BUTTON_7,
- NDOF_BUTTON_8,
- NDOF_BUTTON_9,
- NDOF_BUTTON_10,
+ NDOF_BUTTON_1 = 0x01aa, /* 426 */
+ NDOF_BUTTON_2 = 0x01ab, /* 427 */
+ NDOF_BUTTON_3 = 0x01ac, /* 428 */
+ NDOF_BUTTON_4 = 0x01ad, /* 429 */
+ NDOF_BUTTON_5 = 0x01ae, /* 430 */
+ NDOF_BUTTON_6 = 0x01af, /* 431 */
+ NDOF_BUTTON_7 = 0x01b0, /* 432 */
+ NDOF_BUTTON_8 = 0x01b1, /* 433 */
+ NDOF_BUTTON_9 = 0x01b2, /* 434 */
+ NDOF_BUTTON_10 = 0x01b3, /* 435 */
/* more general-purpose buttons */
- NDOF_BUTTON_A,
- NDOF_BUTTON_B,
- NDOF_BUTTON_C,
- /* the end */
- NDOF_LAST,
+ NDOF_BUTTON_A = 0x01b4, /* 436 */
+ NDOF_BUTTON_B = 0x01b5, /* 437 */
+ NDOF_BUTTON_C = 0x01b6, /* 438 */
+
+#define _NDOF_MAX NDOF_BUTTON_C
/* ********** End of Input devices. ********** */
@@ -318,13 +337,13 @@ enum {
EVT_ACTIONZONE_REGION = 0x5001, /* 20481 */
EVT_ACTIONZONE_FULLSCREEN = 0x5011, /* 20497 */
- /* NOTE: these values are saved in keymap files, do not change them but just add new ones */
+ /* NOTE: these values are saved in key-map files, do not change them but just add new ones. */
/* Tweak events:
* Sent as additional event with the mouse coordinates
* from where the initial click was placed. */
- /* tweak events for L M R mousebuttons */
+ /* Tweak events for L M R mouse-buttons. */
EVT_TWEAK_L = 0x5002, /* 20482 */
EVT_TWEAK_M = 0x5003, /* 20483 */
EVT_TWEAK_R = 0x5004, /* 20484 */
@@ -348,9 +367,11 @@ enum {
/* ********** End of Blender internal events. ********** */
};
-/* *********** wmEvent.type helpers. ********** */
+/* -------------------------------------------------------------------- */
+/** \name #wmEvent.type Helpers
+ * \{ */
-/* test whether the event is timer event */
+/** Test whether the event is timer event. */
#define ISTIMER(event_type) ((event_type) >= TIMER && (event_type) <= TIMERF)
/* for event checks */
@@ -359,22 +380,24 @@ enum {
// #define ISTEXTINPUT(event_type) ((event_type) >= ' ' && (event_type) <= 255)
/* NOTE: an alternative could be to check `event->utf8_buf`. */
-/* test whether the event is a key on the keyboard */
+/** Test whether the event is a key on the keyboard (including modifier keys). */
#define ISKEYBOARD(event_type) \
- (((event_type) >= 0x0020 && (event_type) <= 0x00ff) || \
- ((event_type) >= 0x012c && (event_type) <= 0x0143))
+ (((event_type) >= _EVT_KEYBOARD_MIN && (event_type) <= _EVT_KEYBOARD_MAX) || \
+ ((event_type) >= EVT_F1KEY && (event_type) <= EVT_F24KEY))
-/* test whether the event is a modifier key */
+/** Test whether the event is a modifier key. */
#define ISKEYMODIFIER(event_type) \
(((event_type) >= EVT_LEFTCTRLKEY && (event_type) <= EVT_LEFTSHIFTKEY) || \
(event_type) == EVT_OSKEY)
-/* test whether the event is a mouse button */
+/** Test whether the event is a mouse button. */
#define ISMOUSE(event_type) \
(((event_type) >= LEFTMOUSE && (event_type) <= BUTTON7MOUSE) || (event_type) == MOUSESMARTZOOM)
-
+/** Test whether the event is a mouse wheel. */
#define ISMOUSE_WHEEL(event_type) ((event_type) >= WHEELUPMOUSE && (event_type) <= WHEELOUTMOUSE)
+/** Test whether the event is a mouse (track-pad) gesture. */
#define ISMOUSE_GESTURE(event_type) ((event_type) >= MOUSEPAN && (event_type) <= MOUSEROTATE)
+/** Test whether the event is a mouse button (excluding mouse-wheel). */
#define ISMOUSE_BUTTON(event_type) \
(ELEM(event_type, \
LEFTMOUSE, \
@@ -385,16 +408,16 @@ enum {
BUTTON6MOUSE, \
BUTTON7MOUSE))
-/* test whether the event is tweak event */
+/** Test whether the event is tweak event. */
#define ISTWEAK(event_type) ((event_type) >= EVT_TWEAK_L && (event_type) <= EVT_TWEAK_R)
-/* test whether the event is a NDOF event */
-#define ISNDOF(event_type) ((event_type) >= NDOF_MOTION && (event_type) < NDOF_LAST)
+/** Test whether the event is a NDOF event. */
+#define ISNDOF(event_type) ((event_type) >= _NDOF_MIN && (event_type) <= _NDOF_MAX)
#define IS_EVENT_ACTIONZONE(event_type) \
ELEM(event_type, EVT_ACTIONZONE_AREA, EVT_ACTIONZONE_REGION, EVT_ACTIONZONE_FULLSCREEN)
-/* test whether event type is acceptable as hotkey, excluding modifiers */
+/** Test whether event type is acceptable as hotkey (excluding modifiers). */
#define ISHOTKEY(event_type) \
((ISKEYBOARD(event_type) || ISMOUSE(event_type) || ISNDOF(event_type)) && \
(ISKEYMODIFIER(event_type) == false))
@@ -409,23 +432,23 @@ enum {
#define IS_EVENT_MOD(...) VA_NARGS_CALL_OVERLOAD(_VA_IS_EVENT_MOD, __VA_ARGS__)
enum eEventType_Mask {
- /* ISKEYMODIFIER */
+ /** #ISKEYMODIFIER */
EVT_TYPE_MASK_KEYBOARD_MODIFIER = (1 << 0),
- /* ISKEYBOARD */
+ /** #ISKEYBOARD */
EVT_TYPE_MASK_KEYBOARD = (1 << 1),
- /* ISMOUSE_WHEEL */
+ /** #ISMOUSE_WHEEL */
EVT_TYPE_MASK_MOUSE_WHEEL = (1 << 2),
- /* ISMOUSE_BUTTON */
+ /** #ISMOUSE_BUTTON */
EVT_TYPE_MASK_MOUSE_GESTURE = (1 << 3),
- /* ISMOUSE_GESTURE */
+ /** #ISMOUSE_GESTURE */
EVT_TYPE_MASK_MOUSE_BUTTON = (1 << 4),
- /* ISMOUSE */
+ /** #ISMOUSE */
EVT_TYPE_MASK_MOUSE = (1 << 5),
- /* ISNDOF */
+ /** #ISNDOF */
EVT_TYPE_MASK_NDOF = (1 << 6),
- /* ISTWEAK */
+ /** #ISTWEAK */
EVT_TYPE_MASK_TWEAK = (1 << 7),
- /* IS_EVENT_ACTIONZONE */
+ /** #IS_EVENT_ACTIONZONE */
EVT_TYPE_MASK_ACTIONZONE = (1 << 8),
};
#define EVT_TYPE_MASK_ALL \
@@ -438,7 +461,11 @@ enum eEventType_Mask {
bool WM_event_type_mask_test(int event_type, enum eEventType_Mask mask);
-/* ********** wmEvent.val ********** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name #wmEvent.val Values
+ * \{ */
/* Gestures */
/* NOTE: these values are saved in keymap files, do not change them but just add new ones */
@@ -505,6 +532,8 @@ enum {
GESTURE_MODAL_FLIP = 14,
};
+/** \} */
+
#ifdef __cplusplus
}
#endif