您当前的位置:首页 > IT编程 > C++
| C语言 | Java | VB | VC | python | Android | TensorFlow | C++ | oracle | 学术与代码 | cnn卷积神经网络 | gnn | 图像修复 | Keras | 数据集 | Neo4j | 自然语言处理 | 深度学习 | 医学CAD | 医学影像 | 超参数 | pointnet | pytorch | 异常检测 | Transformers | 情感分类 | 知识图谱 |

自学教程:C++ BKE_paint_get_active_from_context函数代码示例

51自学网 2021-06-01 19:50:53
  C++
这篇教程C++ BKE_paint_get_active_from_context函数代码示例写得很实用,希望能帮到您。

本文整理汇总了C++中BKE_paint_get_active_from_context函数的典型用法代码示例。如果您正苦于以下问题:C++ BKE_paint_get_active_from_context函数的具体用法?C++ BKE_paint_get_active_from_context怎么用?C++ BKE_paint_get_active_from_context使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。

在下文中一共展示了BKE_paint_get_active_from_context函数的21个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于我们的系统推荐出更棒的C++代码示例。

示例1: paint_curve_poll

bool paint_curve_poll(bContext *C){  Object *ob = CTX_data_active_object(C);  Paint *p;  RegionView3D *rv3d = CTX_wm_region_view3d(C);  SpaceImage *sima;  if (rv3d && !(ob && ((ob->mode & OB_MODE_ALL_PAINT) != 0))) {    return false;  }  sima = CTX_wm_space_image(C);  if (sima && sima->mode != SI_MODE_PAINT) {    return false;  }  p = BKE_paint_get_active_from_context(C);  if (p && p->brush && (p->brush->flag & BRUSH_CURVE)) {    return true;  }  return false;}
开发者ID:dfelinto,项目名称:blender,代码行数:25,


示例2: paintcurve_delete_point_exec

static int paintcurve_delete_point_exec(bContext *C, wmOperator *op){	Paint *p = BKE_paint_get_active_from_context(C);	Brush *br = p->brush;	PaintCurve *pc;	PaintCurvePoint *pcp;	wmWindow *window = CTX_wm_window(C);	ARegion *ar = CTX_wm_region(C);	int i;	int tot_del = 0;	pc = br->paint_curve;	if (!pc || pc->tot_points == 0) {		return OPERATOR_CANCELLED;	}	ED_paintcurve_undo_push(C, op, pc);#define DELETE_TAG 2	for (i = 0, pcp = pc->points; i < pc->tot_points; i++, pcp++) {		if (BEZT_ISSEL_ANY(&pcp->bez)) {			pcp->bez.f2 |= DELETE_TAG;			tot_del++;		}	}	if (tot_del > 0) {		int j = 0;		int new_tot = pc->tot_points - tot_del;		PaintCurvePoint *points_new = NULL;		if (new_tot > 0)			points_new = MEM_mallocN(new_tot * sizeof(PaintCurvePoint), "PaintCurvePoint");		for (i = 0, pcp = pc->points; i < pc->tot_points; i++, pcp++) {			if (!(pcp->bez.f2 & DELETE_TAG)) {				points_new[j] = pc->points[i];				if ((i + 1) == pc->add_index) {					BKE_paint_curve_clamp_endpoint_add_index(pc, j);				}				j++;			}			else if ((i + 1) == pc->add_index) {				/* prefer previous point */				pc->add_index = j;			}		}		MEM_freeN(pc->points);		pc->points = points_new;		pc->tot_points = new_tot;	}#undef DELETE_TAG	WM_paint_cursor_tag_redraw(window, ar);	return OPERATOR_FINISHED;}
开发者ID:mgschwan,项目名称:blensor,代码行数:60,


示例3: paint_draw_smooth_cursor

/*** Cursors ***/static void paint_draw_smooth_cursor(bContext *C, int x, int y, void *customdata){  Paint *paint = BKE_paint_get_active_from_context(C);  Brush *brush = BKE_paint_brush(paint);  PaintStroke *stroke = customdata;  if (stroke && brush) {    GPU_line_smooth(true);    GPU_blend(true);    ARegion *ar = stroke->vc.ar;    uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);    immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);    immUniformColor4ubv(paint->paint_cursor_col);    immBegin(GPU_PRIM_LINES, 2);    immVertex2f(pos, x, y);    immVertex2f(pos,                stroke->last_mouse_position[0] + ar->winrct.xmin,                stroke->last_mouse_position[1] + ar->winrct.ymin);    immEnd();    immUnbindProgram();    GPU_blend(false);    GPU_line_smooth(false);  }}
开发者ID:dfelinto,项目名称:blender,代码行数:31,


示例4: paintcurve_point_add

static void paintcurve_point_add(bContext *C,  wmOperator *op, const int loc[2]){	Paint *p = BKE_paint_get_active_from_context(C);	Brush *br = p->brush;	Main *bmain = CTX_data_main(C);	PaintCurve *pc;	PaintCurvePoint *pcp;	wmWindow *window = CTX_wm_window(C);	ARegion *ar = CTX_wm_region(C);	float vec[3] = {loc[0], loc[1], 0.0};	int add_index;	int i;	pc = br->paint_curve;	if (!pc) {		br->paint_curve = pc = BKE_paint_curve_add(bmain, "PaintCurve");	}	ED_paintcurve_undo_push_begin(op->type->name);	pcp = MEM_mallocN((pc->tot_points + 1) * sizeof(PaintCurvePoint), "PaintCurvePoint");	add_index = pc->add_index;	if (pc->points) {		if (add_index > 0)			memcpy(pcp, pc->points, add_index * sizeof(PaintCurvePoint));		if (add_index < pc->tot_points)			memcpy(pcp + add_index + 1, pc->points + add_index, (pc->tot_points - add_index) * sizeof(PaintCurvePoint));		MEM_freeN(pc->points);	}	pc->points = pcp;	pc->tot_points++;	/* initialize new point */	memset(&pcp[add_index], 0, sizeof(PaintCurvePoint));	copy_v3_v3(pcp[add_index].bez.vec[0], vec);	copy_v3_v3(pcp[add_index].bez.vec[1], vec);	copy_v3_v3(pcp[add_index].bez.vec[2], vec);	/* last step, clear selection from all bezier handles expect the next */	for (i = 0; i < pc->tot_points; i++) {		pcp[i].bez.f1 = pcp[i].bez.f2 = pcp[i].bez.f3 = 0;	}	BKE_paint_curve_clamp_endpoint_add_index(pc, add_index);	if (pc->add_index != 0) {		pcp[add_index].bez.f3 = SELECT;		pcp[add_index].bez.h2 = HD_ALIGN;	}	else {		pcp[add_index].bez.f1 = SELECT;		pcp[add_index].bez.h1 = HD_ALIGN;	}	ED_paintcurve_undo_push_end();	WM_paint_cursor_tag_redraw(window, ar);}
开发者ID:wchargin,项目名称:blender,代码行数:60,


示例5: paintcurve_slide_invoke

static int paintcurve_slide_invoke(bContext *C, wmOperator *op, const wmEvent *event){  Paint *p = BKE_paint_get_active_from_context(C);  const float loc_fl[2] = {UNPACK2(event->mval)};  char select;  int i;  bool do_select = RNA_boolean_get(op->ptr, "select");  bool align = RNA_boolean_get(op->ptr, "align");  Brush *br = p->brush;  PaintCurve *pc = br->paint_curve;  PaintCurvePoint *pcp;  if (!pc) {    return OPERATOR_PASS_THROUGH;  }  if (do_select) {    pcp = paintcurve_point_get_closest(pc, loc_fl, align, PAINT_CURVE_SELECT_THRESHOLD, &select);  }  else {    pcp = NULL;    /* just find first selected point */    for (i = 0; i < pc->tot_points; i++) {      if ((select = paintcurve_point_side_index(&pc->points[i].bez, i == 0, SEL_F3))) {        pcp = &pc->points[i];        break;      }    }  }  if (pcp) {    ARegion *ar = CTX_wm_region(C);    wmWindow *window = CTX_wm_window(C);    PointSlideData *psd = MEM_mallocN(sizeof(PointSlideData), "PointSlideData");    copy_v2_v2_int(psd->initial_loc, event->mval);    psd->event = event->type;    psd->pcp = pcp;    psd->select = paintcurve_point_co_index(select);    for (i = 0; i < 3; i++) {      copy_v2_v2(psd->point_initial_loc[i], pcp->bez.vec[i]);    }    psd->align = align;    op->customdata = psd;    /* first, clear all selection from points */    for (i = 0; i < pc->tot_points; i++) {      pc->points[i].bez.f1 = pc->points[i].bez.f3 = pc->points[i].bez.f2 = 0;    }    /* only select the active point */    PAINT_CURVE_POINT_SELECT(pcp, psd->select);    BKE_paint_curve_clamp_endpoint_add_index(pc, pcp - pc->points);    WM_event_add_modal_handler(C, op);    WM_paint_cursor_tag_redraw(window, ar);    return OPERATOR_RUNNING_MODAL;  }  return OPERATOR_PASS_THROUGH;}
开发者ID:dfelinto,项目名称:blender,代码行数:60,


示例6: palette_poll

static int palette_poll(bContext *C){	Paint *paint = BKE_paint_get_active_from_context(C);	if (paint && paint->palette != NULL)		return true;	return false;}
开发者ID:Moguri,项目名称:blender,代码行数:9,


示例7: paintcurve_new_exec

static int paintcurve_new_exec(bContext *C, wmOperator *UNUSED(op)){	Paint *p = BKE_paint_get_active_from_context(C);	Main *bmain = CTX_data_main(C);	if (p && p->brush) {		p->brush->paint_curve = BKE_paint_curve_add(bmain, "PaintCurve");	}	return OPERATOR_FINISHED;}
开发者ID:mgschwan,项目名称:blensor,代码行数:11,


示例8: brush_curve_preset_exec

static int brush_curve_preset_exec(bContext *C, wmOperator *op){	Brush *br = BKE_paint_brush(BKE_paint_get_active_from_context(C));	if (br) {		Scene *scene = CTX_data_scene(C);		BKE_brush_curve_preset(br, RNA_enum_get(op->ptr, "shape"));		BKE_paint_invalidate_cursor_overlay(scene, br->curve);	}	return OPERATOR_FINISHED;}
开发者ID:sftd,项目名称:blender,代码行数:12,


示例9: palette_color_delete_exec

static int palette_color_delete_exec(bContext *C, wmOperator *UNUSED(op)){	Paint *paint = BKE_paint_get_active_from_context(C);	Palette *palette = paint->palette;	PaletteColor *color = BLI_findlink(&palette->colors, palette->active_color);	if (color) {		BKE_palette_color_remove(palette, color);	}	return OPERATOR_FINISHED;}
开发者ID:Moguri,项目名称:blender,代码行数:12,


示例10: palette_new_exec

static int palette_new_exec(bContext *C, wmOperator *UNUSED(op)){	Paint *paint = BKE_paint_get_active_from_context(C);	Main *bmain = CTX_data_main(C);	Palette *palette;	palette = BKE_palette_add(bmain, "Palette");	BKE_paint_palette_set(paint, palette);	return OPERATOR_FINISHED;}
开发者ID:Moguri,项目名称:blender,代码行数:12,


示例11: paintcurve_new_exec

static int paintcurve_new_exec(bContext *C, wmOperator *UNUSED(op)){  Paint *p = BKE_paint_get_active_from_context(C);  Main *bmain = CTX_data_main(C);  if (p && p->brush) {    p->brush->paint_curve = BKE_paint_curve_add(bmain, "PaintCurve");  }  WM_event_add_notifier(C, NC_PAINTCURVE | NA_ADDED, NULL);  return OPERATOR_FINISHED;}
开发者ID:dfelinto,项目名称:blender,代码行数:13,


示例12: stencil_control_poll

static int stencil_control_poll(bContext *C){	PaintMode mode = BKE_paintmode_get_active_from_context(C);	Paint *paint;	Brush *br;	if (!paint_supports_texture(mode))		return false;	paint = BKE_paint_get_active_from_context(C);	br = BKE_paint_brush(paint);	return (br &&	        (br->mtex.brush_map_mode == MTEX_MAP_MODE_STENCIL ||	         br->mask_mtex.brush_map_mode == MTEX_MAP_MODE_STENCIL));}
开发者ID:Moguri,项目名称:blender,代码行数:16,


示例13: brush_reset_exec

static int brush_reset_exec(bContext *C, wmOperator *UNUSED(op)){	Paint *paint = BKE_paint_get_active_from_context(C);	Brush *brush = BKE_paint_brush(paint);	Object *ob = CTX_data_active_object(C);	if (!ob || !brush) return OPERATOR_CANCELLED;	/* TODO: other modes */	if (ob->mode & OB_MODE_SCULPT) {		BKE_brush_sculpt_reset(brush);	}	else {		return OPERATOR_CANCELLED;	}	WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, brush);	return OPERATOR_FINISHED;}
开发者ID:mgschwan,项目名称:blensor,代码行数:19,


示例14: brush_add_exec

/* Brush operators */static int brush_add_exec(bContext *C, wmOperator *UNUSED(op)){	/*int type = RNA_enum_get(op->ptr, "type");*/	Paint *paint = BKE_paint_get_active_from_context(C);	Brush *br = BKE_paint_brush(paint);	Main *bmain = CTX_data_main(C);	ePaintMode mode = BKE_paintmode_get_active_from_context(C);	if (br) {		br = BKE_brush_copy(bmain, br);	}	else {		br = BKE_brush_add(bmain, "Brush", BKE_paint_object_mode_from_paint_mode(mode));		id_us_min(&br->id);  /* fake user only */	}	BKE_paint_brush_set(paint, br);	return OPERATOR_FINISHED;}
开发者ID:mgschwan,项目名称:blensor,代码行数:21,


示例15: paint_draw_line_cursor

static void paint_draw_line_cursor(bContext *C, int x, int y, void *customdata){  Paint *paint = BKE_paint_get_active_from_context(C);  PaintStroke *stroke = customdata;  GPU_line_smooth(true);  uint shdr_pos = GPU_vertformat_attr_add(      immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);  immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);  float viewport_size[4];  GPU_viewport_size_get_f(viewport_size);  immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);  immUniform1i("colors_len", 2); /* "advanced" mode */  const float alpha = (float)paint->paint_cursor_col[3] / 255.0f;  immUniformArray4fv(      "colors", (float *)(float[][4]){{0.0f, 0.0f, 0.0f, alpha}, {1.0f, 1.0f, 1.0f, alpha}}, 2);
开发者ID:dfelinto,项目名称:blender,代码行数:20,


示例16: brush_scale_size_exec

static int brush_scale_size_exec(bContext *C, wmOperator *op){	Scene *scene = CTX_data_scene(C);	Paint  *paint =  BKE_paint_get_active_from_context(C);	Brush  *brush =  BKE_paint_brush(paint);	// Object *ob = CTX_data_active_object(C);	float scalar = RNA_float_get(op->ptr, "scalar");	if (brush) {		// pixel radius		{			const int old_size = BKE_brush_size_get(scene, brush);			int size = (int)(scalar * old_size);			if (abs(old_size - size) < U.pixelsize) {				if (scalar > 1) {					size += U.pixelsize;				}				else if (scalar < 1) {					size -= U.pixelsize;				}			}			BKE_brush_size_set(scene, brush, size);		}		// unprojected radius		{			float unprojected_radius = scalar * BKE_brush_unprojected_radius_get(scene, brush);			if (unprojected_radius < 0.001f) // XXX magic number				unprojected_radius = 0.001f;			BKE_brush_unprojected_radius_set(scene, brush, unprojected_radius);		}		WM_main_add_notifier(NC_BRUSH | NA_EDITED, brush);	}	return OPERATOR_FINISHED;}
开发者ID:Moguri,项目名称:blender,代码行数:41,


示例17: paint_sample_color

/* used for both 3d view and image window */void paint_sample_color(const bContext *C, ARegion *ar, int x, int y)    /* frontbuf */{	Brush *br = BKE_paint_brush(BKE_paint_get_active_from_context(C));	unsigned int col;	char *cp;	CLAMP(x, 0, ar->winx);	CLAMP(y, 0, ar->winy);		glReadBuffer(GL_FRONT);	glReadPixels(x + ar->winrct.xmin, y + ar->winrct.ymin, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);	glReadBuffer(GL_BACK);	cp = (char *)&col;		if (br) {		br->rgb[0] = cp[0] / 255.0f;		br->rgb[1] = cp[1] / 255.0f;		br->rgb[2] = cp[2] / 255.0f;	}}
开发者ID:YasirArafath,项目名称:blender-git,代码行数:22,


示例18: palette_color_add_exec

static int palette_color_add_exec(bContext *C, wmOperator *UNUSED(op)){	Scene *scene = CTX_data_scene(C);	Paint *paint = BKE_paint_get_active_from_context(C);	Brush *brush = paint->brush;	PaintMode mode = BKE_paintmode_get_active_from_context(C);	Palette *palette = paint->palette;	PaletteColor *color;	color = BKE_palette_color_add(palette);	palette->active_color = BLI_listbase_count(&palette->colors) - 1;	if (ELEM(mode, ePaintTextureProjective, ePaintTexture2D, ePaintVertex)) {		copy_v3_v3(color->rgb, BKE_brush_color_get(scene, brush));		color->value = 0.0;	}	else if (mode == ePaintWeight) {		zero_v3(color->rgb);		color->value = brush->weight;	}	return OPERATOR_FINISHED;}
开发者ID:Moguri,项目名称:blender,代码行数:23,


示例19: brush_curve_preset_poll

static int brush_curve_preset_poll(bContext *C){	Brush *br = BKE_paint_brush(BKE_paint_get_active_from_context(C));	return br && br->curve;}
开发者ID:sftd,项目名称:blender,代码行数:6,


示例20: paintcurve_point_select

static bool paintcurve_point_select(    bContext *C, wmOperator *op, const int loc[2], bool toggle, bool extend){  wmWindow *window = CTX_wm_window(C);  ARegion *ar = CTX_wm_region(C);  Paint *p = BKE_paint_get_active_from_context(C);  Brush *br = p->brush;  PaintCurve *pc;  int i;  const float loc_fl[2] = {UNPACK2(loc)};  pc = br->paint_curve;  if (!pc) {    return false;  }  ED_paintcurve_undo_push_begin(op->type->name);  if (toggle) {    PaintCurvePoint *pcp;    char select = 0;    bool selected = false;    pcp = pc->points;    for (i = 0; i < pc->tot_points; i++) {      if (pcp[i].bez.f1 || pcp[i].bez.f2 || pcp[i].bez.f3) {        selected = true;        break;      }    }    if (!selected) {      select = SELECT;    }    for (i = 0; i < pc->tot_points; i++) {      pc->points[i].bez.f1 = pc->points[i].bez.f2 = pc->points[i].bez.f3 = select;    }  }  else {    PaintCurvePoint *pcp;    char selflag;    pcp = paintcurve_point_get_closest(pc, loc_fl, false, PAINT_CURVE_SELECT_THRESHOLD, &selflag);    if (pcp) {      BKE_paint_curve_clamp_endpoint_add_index(pc, pcp - pc->points);      if (selflag == SEL_F2) {        if (extend) {          pcp->bez.f2 ^= SELECT;        }        else {          pcp->bez.f2 |= SELECT;        }      }      else if (selflag == SEL_F1) {        if (extend) {          pcp->bez.f1 ^= SELECT;        }        else {          pcp->bez.f1 |= SELECT;        }      }      else if (selflag == SEL_F3) {        if (extend) {          pcp->bez.f3 ^= SELECT;        }        else {          pcp->bez.f3 |= SELECT;        }      }    }    /* clear selection for unselected points if not extending and if a point has been selected */    if (!extend && pcp) {      for (i = 0; i < pc->tot_points; i++) {        pc->points[i].bez.f1 = pc->points[i].bez.f2 = pc->points[i].bez.f3 = 0;        if ((pc->points + i) == pcp) {          char index = paintcurve_point_co_index(selflag);          PAINT_CURVE_POINT_SELECT(pcp, index);        }      }    }    if (!pcp) {      ED_paintcurve_undo_push_end();      return false;    }  }  ED_paintcurve_undo_push_end();  WM_paint_cursor_tag_redraw(window, ar);  return true;}
开发者ID:dfelinto,项目名称:blender,代码行数:100,


示例21: buttons_texture_users_from_context

static void buttons_texture_users_from_context(ListBase *users,                                               const bContext *C,                                               SpaceProperties *sbuts){  Scene *scene = NULL;  Object *ob = NULL;  FreestyleLineStyle *linestyle = NULL;  Brush *brush = NULL;  ID *pinid = sbuts->pinid;  bool limited_mode = (sbuts->flag & SB_TEX_USER_LIMITED) != 0;  /* get data from context */  if (pinid) {    if (GS(pinid->name) == ID_SCE) {      scene = (Scene *)pinid;    }    else if (GS(pinid->name) == ID_OB) {      ob = (Object *)pinid;    }    else if (GS(pinid->name) == ID_BR) {      brush = (Brush *)pinid;    }    else if (GS(pinid->name) == ID_LS) {      linestyle = (FreestyleLineStyle *)pinid;    }  }  if (!scene) {    scene = CTX_data_scene(C);  }  const ID_Type id_type = pinid != NULL ? GS(pinid->name) : -1;  if (!pinid || id_type == ID_SCE) {    wmWindow *win = CTX_wm_window(C);    ViewLayer *view_layer = (win->scene == scene) ? WM_window_get_active_view_layer(win) :                                                    BKE_view_layer_default_view(scene);    brush = BKE_paint_brush(BKE_paint_get_active_from_context(C));    linestyle = BKE_linestyle_active_from_view_layer(view_layer);    ob = OBACT(view_layer);  }  /* fill users */  BLI_listbase_clear(users);  if (linestyle && !limited_mode) {    buttons_texture_users_find_nodetree(        users, &linestyle->id, linestyle->nodetree, N_("Line Style"));  }  if (ob) {    ParticleSystem *psys = psys_get_current(ob);    MTex *mtex;    int a;    /* modifiers */    modifiers_foreachTexLink(ob, buttons_texture_modifier_foreach, users);    /* grease pencil modifiers */    BKE_gpencil_modifiers_foreachTexLink(ob, buttons_texture_modifier_gpencil_foreach, users);    /* particle systems */    if (psys && !limited_mode) {      for (a = 0; a < MAX_MTEX; a++) {        mtex = psys->part->mtex[a];        if (mtex) {          PointerRNA ptr;          PropertyRNA *prop;          RNA_pointer_create(&psys->part->id, &RNA_ParticleSettingsTextureSlot, mtex, &ptr);          prop = RNA_struct_find_property(&ptr, "texture");          buttons_texture_user_property_add(users,                                            &psys->part->id,                                            ptr,                                            prop,                                            N_("Particles"),                                            RNA_struct_ui_icon(&RNA_ParticleSettings),                                            psys->name);        }      }    }    /* field */    if (ob->pd && ob->pd->forcefield == PFIELD_TEXTURE) {      PointerRNA ptr;      PropertyRNA *prop;      RNA_pointer_create(&ob->id, &RNA_FieldSettings, ob->pd, &ptr);      prop = RNA_struct_find_property(&ptr, "texture");      buttons_texture_user_property_add(          users, &ob->id, ptr, prop, N_("Fields"), ICON_FORCE_TEXTURE, IFACE_("Texture Field"));    }  }  /* brush */  if (brush) {    PointerRNA ptr;//.........这里部分代码省略.........
开发者ID:dfelinto,项目名称:blender,代码行数:101,



注:本文中的BKE_paint_get_active_from_context函数示例整理自Github/MSDocs等源码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。


C++ BKE_report函数代码示例
C++ BKE_libblock_alloc函数代码示例
万事OK自学网:51自学网_软件自学网_CAD自学网自学excel、自学PS、自学CAD、自学C语言、自学css3实例,是一个通过网络自主学习工作技能的自学平台,网友喜欢的软件自学网站。