原文链接
原文格式太乱了,我整理了一下
正文
Blender Modifier 的结构有点小复杂, 需要修改的部分有点多
需要修改的部分
1. properties_data_modifier.py
Modifier 的 UI 界面, 接口是 SCALING
2. DNA_modifier_types.h
这里有两个东西需要修改
- a. 在这里添加
ModifierType枚举类 - b. 声明和 UI 交互的数据结构
3. RNA_access.h
添加 StructRNA 的声明, 而定义是自动生成的
4. rna_modifier.c
这里有三处需要修改
- a. 这里添加的是 添加 Modifier 下拉列表 UI 的值, 同时指向 1 和 2.a
- b. 修改
rna_Modifier_refine, 这里相当于定义了从 2.a 到 3 的链接 - c. 在
RNA_def_modifier中创建StructRNA, 然后由系统自动生成定义, 和 3 链接
5. 创建 Modifier 所需的文件 MOD_xxx.c
这个文件包含所有算法, 以及事件处理, 修改 cmakelists 加入编译列表
6. 在 MOD_modifiertypes.h 中声明 Modifier 所需要的类型
将会在 5 中定义
7. 在 MOD_util.c 创建 INIT_TYPE
相当于从 2.a 到 6 的链接
这是一个简易的关系图:
具体代码解析
1. 首先是编写 UI
我们在 properties_data_modifier.py 添加这么行代码
class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
...
def SCALING(self, layout, ob, md):
layout.prop(md, "scaleui")
...
SCALING 这个函数是有意义的, 在第 4.a 步会出现, 同时这里的 md 就是我们在第 4.c 步创建的 RNA_ScalingModifier
2. DNA_modifier_types.h: 修改两处
第一处
在 ModifierType 枚举类中创建 eModifierType_Scaling, 这是 blender 最顶层能够访问到的元素
typedef enum ModifierType {
eModifierType_None = 0,
...
...
eModifierType_Wireframe = 48,
eModifierType_Scaling = 49, // 这里的编号是需要连续
NUM_MODIFIER_TYPES
} ModifierType;
第二处
创建 struct ScalingModifierData, 这个 struct 会在两处用到, 一个是生成 RNA_ScalingModifier, 第二个是在 MOD_scaling.c 中用到
typedef struct ScalingModifierData {
ModifierData modifier;
float scale;
int pad; // blender 为了保证兼容性的 8 byte 对齐
} ScalingModifierData;
3. RNA_access.h
声明 RNA_ScalingModifier ,其实际定义由在 4.c 步骤生成
extern StructRNA RNA_ScalingModifier
4. rna_modifier.c
修改三处
第一处
在这里可以看到各种被分类好了的 Modifier, 找到对应的位置插入以下代码:
EnumPropertyItem modifier_type_items[] = {
...
{0, "", 0, N_("Deform"), ""},
...
{eModifierType_Scaling, "SCALING", ICON_MAN_SCALE, "Scaling the mesh", ""},
...
};
这一步同时让系统知道 eModifierType_Scaling 对应了 Python 中的哪个函数来绘制 UI
第二处
在函数体 rna_Modifier_refine 中添加对应代码:
static StructRNA *rna_Modifier_refine(struct PointerRNA *ptr)
{
...
switch (md->type) {
...
case eModifierType_Scaling:
return &RNA_ScalingModifier;
...
}
这里让系统得知 eModifierType_Scaling 对应的 RNA
第三处
定义 RNA
static void rna_def_modifier_scaling(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
srna = RNA_def_struct(brna, "ScalingModifier", "Modifier");
RNA_def_struct_ui_text(srna, "Scaling Modifier", "Scaling effect modifier");
RNA_def_struct_sdna(srna, "ScalingModifierData");
RNA_def_struct_ui_icon(srna, ICON_MAN_SCALE);
/* scaleui: name for "properties_data_modifier.py"*/
prop = RNA_def_property(srna, "scaleui", PROP_FLOAT, PROP_NONE);
/*scale: name for "DNA_modifier_types.h"*/
RNA_def_property_float_sdna(prop, NULL, "scale");
RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
RNA_def_property_ui_range(prop, -100, 100, 1, 3);
RNA_def_property_ui_text(prop, "Scale", "Scale factor");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
}
......
void RNA_def_modifier(BlenderRNA *brna)
{
...
rna_def_modifier_remesh(brna);
rna_def_modifier_skin(brna);
rna_def_modifier_scaling(brna);
}
5. 创建对应文件, 修改对应文件夹下的 cmakelists
set(SRC
...
intern/MOD_scaling.c
...
)
6. OD_modifiertypes.h
添加 ModifierTypeInfo 的声明
extern ModifierTypeInfo modifierType_Scaling;
7. MOD_util.c
让 blender 能够通过 eModifierType_Scaling 获取 ModifierTypeInfo
#define INIT_TYPE(typeName) (types[eModifierType_##typeName] = &modifierType_##typeName)
...
INIT_TYPE(Scaling);
#undef INIT_TYPE
8. MOD_util.c
核心代码部分, 关于 ModifierTypeInfo 的定义可以在 BKE_modifier.h 中看到非常详细的定义
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2005 by the Blender Foundation.
* All rights reserved.
*
* Contributor(s): Your name
*
* ***** END GPL LICENSE BLOCK *****
*
*/
/** \file blender/modifiers/intern/MOD_scaling.c
* \ingroup modifiers
*/
#include "DNA_meshdata_types.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "BLI_string.h"
#include "MEM_guardedalloc.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_particle.h"
#include "BKE_deform.h"
#include "MOD_modifiertypes.h"
#include "MOD_util.h"
static void initData(ModifierData *md)
{
ScalingModifierData *smd = (ScalingModifierData *) md;
smd->scale = 1.0f;
}
static void copyData(ModifierData *md, ModifierData *target)
{
ScalingModifierData *smd = (ScalingModifierData *) md;
ScalingModifierData *tsmd = (ScalingModifierData *) target;
tsmd->scale = smd->scale;
}
static int isDisabled(ModifierData *md, int UNUSED(useRenderParams))
{
ScalingModifierData *smd = (ScalingModifierData *) md;
/* disable if modifier is 1.0 for scale*/
if (smd->scale == 1.0f) return 1;
return 0;
}
static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
{
ScalingModifierData *smd = (ScalingModifierData *)md;
CustomDataMask dataMask = 0;
return dataMask;
}
static void ScalingModifier_do(
ScalingModifierData *smd, Object *ob, DerivedMesh *dm,
float (*vertexCos)[3], int numVerts)
{
int i;
float scale;
scale = smd->scale;
for (i = 0; i < numVerts; i++) {
vertexCos[i][0] = vertexCos[i][0] * scale;
vertexCos[i][1] = vertexCos[i][1] * scale;
vertexCos[i][2] = vertexCos[i][2] * scale;
}
}
static void deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData,
float (*vertexCos)[3], int numVerts, ModifierApplyFlag UNUSED(flag))
{
DerivedMesh *dm = get_dm(ob, NULL, derivedData, NULL, 0);
ScalingModifier_do((ScalingModifierData *)md, ob, dm,
vertexCos, numVerts);
if (dm != derivedData)
dm->release(dm);
}
static void deformVertsEM(
ModifierData *md, Object *ob, struct BMEditMesh *editData,
DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
{
DerivedMesh *dm = get_dm(ob, editData, derivedData, NULL, 0);
ScalingModifier_do((ScalingModifierData *)md, ob, dm,
vertexCos, numVerts);
if (dm != derivedData)
dm->release(dm);
}
ModifierTypeInfo modifierType_Scaling = {
/* name */ "Scaling",
/* structName */ "ScalingModifierData",
/* structSize */ sizeof(ScalingModifierData),
/* type */ eModifierTypeType_OnlyDeform,
/* flags */ eModifierTypeFlag_AcceptsMesh |
eModifierTypeFlag_SupportsEditmode,
/* copyData */ copyData,
/* deformVerts */ deformVerts,
/* deformMatrices */ NULL,
/* deformVertsEM */ deformVertsEM,
/* deformMatricesEM */ NULL,
/* applyModifier */ NULL,
/* applyModifierEM */ NULL,
/* initData */ initData,
/* requiredDataMask */ requiredDataMask,
/* freeData */ NULL,
/* isDisabled */ isDisabled,
/* updateDepgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
/* foreachObjectLink */ NULL,
/* foreachIDLink */ NULL,
/* foreachTexLink */ NULL,
};
乱
RNA_access.h: 各种StructRNA声明的地方BKE_modifier.h: 关于ModifierTypeInfo的定义