2.80 Cheat Sheet for updating add-ons

add-ons
blender2-80
(nBurn) #1

This is a cheat sheet I originally made for myself to keep track of the Python API changes between 2.79 and 2.80. My goal was was to have a “CTRL F” quick reference I could use to avoid having to dig through API docs and add-on updates every time I wasn’t sure on what code changes were needed for 2.80.

Please read the note at the top related to the ‘???’ and ‘***’ markers throughout the cheat sheet before using this. A large part of this cheat sheet was pulled from git diff reports, so the syntax may not be correct in some cases.

See also

Blender 2.80 add-on update cheat sheet
??? = not verified or not correct in many cases, but may work
*** = verified to work in most or all cases

???  alpha needed
-mat.diffuse_color = (red_v, grn_v, blu_v)  # viewport color
+mat.diffuse_color = (red_v, grn_v, blu_v, alp)  # viewport color

???  viewnumpad
-col.operator("view3d.viewnumpad", text="View Camera", icon='CAMERA_DATA').type = 'CAMERA'
+col.operator("view3d.view_camera", text="View Camera", icon='CAMERA_DATA')

???  viewnumpad
-bpy.ops.view3d.viewnumpad(type='BOTTOM')
+bpy.ops.view3d.view_axis(type='BOTTOM')

???  get_rna
-properties = op.get_rna().bl_rna.properties.items()
+properties = op.get_rna_type().properties.items()

???  viewport_shade
-pie.prop(context.space_data, "viewport_shade", expand=True)
+pie.prop(context.space_data.shading, "type", expand=True)
-if context.space_data.viewport_shade == 'RENDERED':
+if context.space_data.shading.type == 'RENDERED':

???  TOOLS
-bl_region_type = "TOOLS"
+bl_region_type = "UI"

???  View
-bl_region_type = 'View'
-bl_category = 'Tools'
+bl_region_type = 'UI'
+bl_category = 'View'
otherwise...
RuntimeError: Error: Registering panel class: 'view3d.blah' has category 'View'

???  Lamp
-"OUTPUT_LAMP"
-"ShaderNodeOutputLamp"
+"OUTPUT_LIGHT"
+"ShaderNodeOutputLight"

???  lamps
-bpy.data.lamps
+bpy.data.lights

***  select (only changed for objects)
-obj.select = False
+obj.select_set(False)
otherwise...
AttributeError: 'Object' object has no attribute 'select'
possible regex:
find: (\.select\s*=\s*)(True|False)
repl: .select_set\(\2\)

***  select (only changed for objects)
-if o.select:
+if o.select_get():
-if not obj.select:
+if not obj.select_get():
-if o.select is True:
+if o.select_get() is True:
possible regex:
find: (\.select)(\s*)(is|==)(\s*)(True|False)
repl: .select_get\(\)(\2)(\3)(\4)(\5)

???  backdrop_x / backdrop_y
-context.space_data.backdrop_x = 0
-context.space_data.backdrop_y = 0
+context.space_data.backdrop_offset[0] = 0
+context.space_data.backdrop_offset[1] = 0

???  ops.delete context
-bmesh.ops.delete(bm, geom=edges, context=1)
-bmesh.ops.delete(bm, geom=edges, context=2)
-bmesh.ops.delete(bm, geom=edges, context=3)
+bmesh.ops.delete(bm, geom=edges, context="VERTS")
+bmesh.ops.delete(bm, geom=edges, context="EDGES")
+bmesh.ops.delete(bm, geom=edges, context="FACES")
otherwise...
TypeError: delete: keyword "context" expected a string, not int

???  tessface
-bmesh.update_edit_mesh(object.data, tessface=True, destructive=True)
+bmesh.update_edit_mesh(object.data, loop_triangles=True, destructive=True)

???  to_mesh
 ob = bpy.context.active_object
 depsgraph = bpy.context.evaluated_depsgraph_get()
-mesh = ob.evaluated_get(depsgraph).to_mesh()
+ob_eval = ob.evaluated_get(depsgraph)
+mesh = ob_eval.to_mesh()

???  to_mesh (2)
 obj = bpy.context.active_object
-mesh = obj.to_mesh(context.scene, True, 'PREVIEW')
+depsgraph = context.evaluated_depsgraph_get()
+mesh = obj.evaluated_get(depsgraph).to_mesh()

???  meshes.remove
-bpy.data.meshes.remove(mesh)
+ob_eval.to_mesh_clear()

???  active
-plane = context.scene.objects.active
+plane = context.active_object

???  active
-bpy.context.scene.objects.active = obj
+bpy.context.view_layer.objects.active = obj
otherwise...
AttributeError: bpy_prop_collection: attribute "active" not found
#bpy.context.view_layer.objects.active = bpy.data.objects['Light'] ??
#bpy.context.view_layer.objects.active = None ??
#bpy.context.active_object ?

???  object_bases
-context.scene.object_bases
+obj = context.view_layer.objects.active  ??? 

???  frame_set subframe
-context.scene.frame_set(int(frame[1]), frame[0])
+context.scene.frame_set(int(frame[1]), subframe=frame[0])

???  prop text
-row.prop(self, "filter_auto_focus", "", icon='VIEWZOOM')
+row.prop(self, "filter_auto_focus", text="", icon='VIEWZOOM')

???  text (label)
-row.label(context.object.name)
+row.label(text=context.object.name)
-box.label("From curve")
+box.label(text="From curve")

???  show_x_ray
-col.prop(context.active_object, 'show_x_ray', toggle=False, text='X Ray')
+col.prop(context.active_object, 'show_in_front', toggle=False, text='X Ray')

???  popup_menu title
-context.window_manager.popup_menu(self.menu, "Icon Viewer")
+context.window_manager.popup_menu(self.menu, title="Icon Viewer")

???  operator text
-row.operator(IV_OT_panel_menu_call.bl_idname, "", icon='COLLAPSEMENU')
+row.operator(IV_OT_panel_menu_call.bl_idname, text="", icon='COLLAPSEMENU')

***  operator text
-row.operator("wm.url_open", "Google", icon='SOLO_ON'
-            ).url = "https://www.google.com"
+row.operator("wm.url_open", text="Google", icon='SOLO_ON'
+            ).url = "https://www.google.com"

***  label text
-col.label("Sharpness")
+col.label(text="Sharpness")
otherwise...
TypeError: UILayout.label(): required parameter "text" to be a keyword argument!

***  prop text
-row.prop(self, "ctrl", "Ctrl", toggle=True)
+row.prop(self, "ctrl", text="Ctrl", toggle=True)

***  prop text
-col.prop(self.overlay, "alignment", "")
+col.prop(self.overlay, "alignment", text="")

???  hide
-bpy.context.object.hide
+bpy.context.object.hide_viewport

???  Group
-bpy.types.Group()
+bpy.types.Collection()

???  groups
-bpy.data.groups
+bpy.data.collections

???  dupli_group
-context.active_object.dupli_group
+context.active_object.instance_collection

???  link
-scene.objects.link(newCurve)
+coll = context.view_layer.active_layer_collection.collection
+coll.objects.link(newCurve)

???  link
-bpy.context.scene.objects.link(newCurve)
+bpy.context.collection.objects.link(newCurve)
otherwise...
AttributeError: 'bpy_prop_collection' object has no attribute 'link'

???  unlink
-bpy.context.scene.objects.unlink(obj)
+bpy.context.collection.objects.unlink(obj)

???  draw_type
-bpy.context.object.data.draw_type = 'BBONE'
+bpy.context.object.data.display_type = 'BBONE'

???  draw_size
-bpy.data.cameras[cam_data_name].draw_size = 1.0
+bpy.data.cameras[cam_data_name].display_size = 1.0

???  uv_textures name
-me.uv_textures.new("Leaves")
+me.uv_layers.new(name="Leaves")

???  transform_apply location rotation scale
-bpy.ops.object.transform_apply(rotation=True, scale=True)
+bpy.ops.object.transform_apply(location=False, rotation=True, scale=True)

???  ops _add layers
-bpy.ops.mesh.primitive_cube_add(view_align=False, enter_editmode=False, 
-    location=(0.0, 0.0, 0.0), rotation=(0.0, 0.0, 0.0), layers=current_layers)
+bpy.ops.mesh.primitive_cube_add(view_align=False, enter_editmode=False, 
+    location=(0.0, 0.0, 0.0), rotation=(0.0, 0.0, 0.0))

???  view_align
 bpy.ops.curve.primitive_nurbs_path_add(
-  view_align=False, enter_editmode=False, location=(0, 0, 0)
+  align='WORLD', enter_editmode=False, location=(0, 0, 0)
 )

???  radius
-bpy.ops.mesh.primitive_ico_sphere_add(radius=0.2)
+bpy.ops.mesh.primitive_ico_sphere_add(size=0.4)

???  space_data transform_orientation
-orientation = bpy.context.space_data.transform_orientation
-custom = bpy.context.space_data.current_orientation
-bpy.context.space_data.transform_orientation = 'GLOBAL'
+orient_slot = bpy.context.scene.transform_orientation_slots[0]
+custom = orient_slot.custom_orientation
+bpy.context.scene.transform_orientation_slots[0].type = 'GLOBAL'
otherwise...
AttributeError: 'SpaceView3D' object has no attribute 'transform_orientation'

???
bpy.ops.transform.translate
-proportional='DISABLED'
+use_proportional_edit=False

???  constraint_orientation
-bpy.ops.transform.resize('INVOKE_DEFAULT', constraint_axis = axis, constraint_orientation = 'GLOBAL')
+bpy.ops.transform.resize('INVOKE_DEFAULT', constraint_axis = axis, orient_type = 'GLOBAL')

***  user_preferences
-addons = bpy.context.user_preferences.addons
+addons = bpy.context.preferences.addons

???  user_preferences
-bpy.context.user_preferences.system.use_weight_color_range
+bpy.context.preferences.view.use_weight_color_range
"input.active_keyconfig", "keymap.active_keyconfig"
"input.show_ui_keyconfig", "keymap.show_ui_keyconfig"
"system.author", "filepaths.author"
"system.color_picker_type", "view.color_picker_type"
"system.font_path_ui", "view.font_path_ui"
"system.font_path_ui_mono", "view.font_path_ui_mono"
"system.language", "view.language"
"system.text_hinting", "view.text_hinting"
"system.use_international_fonts", "view.use_international_fonts"
"system.use_scripts_auto_execute", "filepaths.use_scripts_auto_execute"
"system.use_tabs_as_spaces", "filepaths.use_tabs_as_spaces"
"system.use_text_antialiasing", "view.use_text_antialiasing"
"system.use_translate_interface", "view.use_translate_interface"
"system.use_translate_new_dataname", "view.use_translate_new_dataname"
"system.use_translate_tooltips", "view.use_translate_tooltips"
"system.use_weight_color_range", "view.use_weight_color_range"
"system.weight_color_range", "view.weight_color_range"
"view.use_auto_perspective", "input.use_auto_perspective"
"view.use_camera_lock_parent", "input.use_camera_lock_parent"
"view.use_cursor_lock_adjust", "input.use_cursor_lock_adjust"
"view.use_mouse_depth_cursor", "input.use_mouse_depth_cursor"
"view.use_mouse_depth_navigate", "input.use_mouse_depth_navigate"
"view.use_quit_dialog", "view.use_save_prompt"
"view.use_rotate_around_active", "input.use_rotate_around_active"
"view.use_zoom_to_mouse", "input.use_zoom_to_mouse"

???  wm.addon_enable
-bpy.ops.wm.addon_enable(module=module)
+bpy.ops.preferences.addon_enable(module=module)

???  wm.addon_userpref_show
-layout.operator("wm.addon_userpref_show",
+layout.operator("preferences.addon_show",

???  select_mouse
-mouse_right = context.user_preferences.inputs.select_mouse
+wm = context.window_manager
+keyconfig = wm.keyconfigs.active
+mouse_right = getattr(keyconfig.preferences, "select_mouse", "LEFT")

***  percentage
-split = row.split(percentage=0.10, align=True)
+split = row.split(factor=0.10, align=True)

***  row align
-row = col.row(True)
+row = col.row(align=True)
otherwise...
TypeError: UILayout.row(): required parameter "align" to be a keyword argument!

***  scene_update_pre
-bpy.app.handlers.scene_update_pre
+bpy.app.handlers.depsgraph_update_pre

***  scene_update_post
-bpy.app.handlers.scene_update_post.append(check_drivers)
+bpy.app.handlers.depsgraph_update_post.append(check_drivers)

???  scene.update
-bpy.context.scene.update()
+bpy.context.view_layer.update()

???  use_occlude_geometry
-space_data.use_occlude_geometry
+space_data.shading.show_xray
otherwise...
AttributeError: 'SpaceView3D' object has no attribute 'use_occlude_geometry'

???  Matrix Multiplication
-normal = rotation * mathutils.Vector((0.0, 0.0, 1.0))
+normal = rotation @ mathutils.Vector((0.0, 0.0, 1.0))

???  viewport_shade
-self.snap_face = context.space_data.viewport_shade not in {'BOUNDBOX', 'WIREFRAME'}
-self.sctx.set_snap_mode(True, True, self.snap_face)
+shading = context.space_data.shading
+self.snap_face = not (snap_edge_and_vert and
+                     (shading.show_xray or shading.type == 'WIREFRAME'))

***  Property (annotations, class def only, not in methods)
-operator = bpy.props.BoolProperty(name="Operator Name", default=True)
+operator: bpy.props.BoolProperty(name="Operator Name", default=True)
"BoolProperty", "CollectionProperty", "EnumProperty", 
"FloatVectorProperty", "FloatProperty", "IntProperty", 
"StringProperty"

???  time_step
-self.timer = wm.event_timer_add(0.05, bpy.context.window)
+self.timer = wm.event_timer_add(time_step=0.05, window=bpy.context.window)

???  subframe
-context.scene.frame_set(10, 0.25)
+context.scene.frame_set(10, subframe=0.25)

???  INFO_MT_
-box.menu("INFO_MT_file_import", icon='IMPORT')
+box.menu("TOPBAR_MT_file_import", icon='IMPORT')

???  _specials
-scene = context.scene.mat_specials
+scene = context.scene.mat_context_menu
-bpy.types.VIEW3D_MT_edit_mesh_specials.prepend(menu_func)
+bpy.types.VIEW3D_MT_edit_mesh_context_menu.prepend(menu_func)

???  tweak_threshold
-tt = context.preferences.inputs.tweak_threshold
+tt = context.preferences.inputs.drag_threshold
otherwise...
rna_uiItemR: property not found: PreferencesInput.tweak_threshold

???  cursor_location
-endvertex = bpy.context.scene.cursor_location
+endvertex = bpy.context.scene.cursor.location

???  snap_element
-bpy.context.tool_settings.snap_element
+bpy.context.tool_settings.snap_elements
otherwise...
AttributeError: 'ToolSettings' object has no attribute 'snap_element'

???  pivot_point
-pivot = bpy.context.space_data.pivot_point
+pivot = bpy.context.tool_settings.transform_pivot_point
otherwise...
AttributeError: 'SpaceView3D' object has no attribute 'pivot_point'

???  proportional_edit
 ts = context.tool_settings
-ts.proportional_edit = 'ENABLED'
+ts.use_proportional_edit = True

???  resetting header_text_set
-bpy.context.area.header_text_set(text='')
+context.area.header_text_set(None)

???  register_module
-bpy.utils.register_module(__name__)
+for cls in classes:
+    bpy.utils.register_class(cls)

???  icon
-row.label(text="Use Properties panel", icon='CURSOR')
+row.label(text="Use Properties panel", icon='PIVOT_CURSOR')
"BUTS", "PROPERTIES"
"CURSOR", "PIVOT_CURSOR"
"FULLSCREEN", "WINDOW"
"IMAGE_COL", "IMAGE"
"IPO", "GRAPH"
"LAMP", "LIGHT"
"LAMP_AREA", "LIGHT_AREA"
"LAMP_DATA", "LIGHT_DATA"
"LAMP_HEMI", "LIGHT_HEMI"
"LAMP_POINT", "LIGHT_POINT"
"LAMP_SPOT", "LIGHT_SPOT"
"LAMP_SUN", "LIGHT_SUN"
"LINK",  #  (maybe use DOT, LAYER_ACTIVE or LAYER_USED)
"LINK_AREA", "LINKED"
"OOPS", "OUTLINER"
"ORTHO", "XRAY"
"OUTLINER_DATA_LAMP", "OUTLINER_DATA_LIGHT"
"OUTLINER_OB_LAMP", "OUTLINER_OB_LIGHT"
"PLUG", "PLUGIN"
"ROTACTIVE", "PIVOT_ACTIVE"
"ROTATECENTER", "PIVOT_MEDIAN"
"ROTATECOLLECTION", "PIVOT_INDIVIDUAL"
"SCRIPTWIN", "PREFERENCES"
"SMOOTH", "SHADING_RENDERED"
"SOLID", "SHADING_SOLID"
"WIRE", "SHADING_WIRE"

"ALIGN", ??
"BBOX", ??
"BORDER_LASSO", ??
"BORDER_RECT", ??
"DOTSDOWN", ??
"DOTSUP", ??
"EDIT", ??
"GAME", ??
"GO_LEFT", ??
"INLINK", ??
"MANIPUL", ??
"MAN_ROT", ??
"MAN_SCALE", ??
"MAN_TRANS", ??
"OOPS", ??
"OPEN_RECENT", ??
"ORTHO", ??
"RADIO", ??
"RECOVER_AUTO", ??
"RENDER_REGION", ??
"ROTACTIVE", ??
"ROTATE", ??
"SAVE_AS", ??
"SAVE_COPY", ??
"SNAP_SURFACE", ??
"SPACE2", ??
"TEMPERATURE", ??
23 Likes
Updating Built In Addons to Blender 2.8
SpeedSculpt
Import/Export Script
How to use node_tree.nodes.add_node(“ShaderNodeTexImage”)
List of addons that work with 2.8
(nBurn) #2

Placeholder post.

(nBurn) #3

Placeholder post 2

(Meta-Androcto) #4

Thanks very much, these are very helpful

(Jason van Gumster) pinned #6
(nBurn) #7

The first 3 posts in this thread are now editable, thanks mods!

Make sure to do a search before doing any edits to avoid adding something that is already there.

2 Likes
(fin.eskimo) #8

Great idea…

(Hiisi) #9
  1. 2.8 API introduces new way of class registration. Instead of module registration now one has to register classes directly.
  2. The redesigned interfaces has some window’ names changed. For instance, INFO_MT_file_import has became TOPBAR_MT_file_import.
  3. bpy.context.user_preferences -> bpy.context.preferences
  4. bpy.ops.wm.addon_enable -> bpy.ops.preferences.addon_enable
  5. bpy.context.scene.objects.active = obj now became bpy.context.view_layer.objects.active = obj
  6. obj.select = True now became obj.select_set(state = True)
(nBurn) #10

Thanks, didn’t have this one in the list.

(Blended_Blue) #11

Nice little list you have created, thanks for posting it!


Recently I have been updating my own legacy code while attempting to maintain support for both versions in a single file.

I have declared LEGACY_MODE as the switch that toggles between the two command sets based on the version tuple provided by bpy.app.version.

Example:

LEGACY_MODE = bpy.app.version < (2, 80, 0) #Switch based on version for Blender 2.8+ or legacy support.
...

...
o = byp.data.object[0]
if LEGACY_MODE:
    o.hide = False #unhide object using legacy commands
else:
    o.hide_viewport = 0 #unhide object using modern commands

Anyways, just felt like sharing something :slight_smile:

1 Like
(kkar) #12

I do that in a similar way too, but it is very tedious :frowning: I now maintain a huge module just for that.

This is especially a big issue with annotations inside classes. I am for now pretending that I do not get those messages.

(nBurn) #13

The World Blender Meetup had a presentation dedicated to this as well. It looked interesting, but I haven’t tried this with my own add-ons. Just getting them running in 2.80 has been enough of job, maybe once the release candidate is out I might give this a try.

(kkar) #14

Thanks for the link. Useful presentation. He has a dedicated page about it.

(Blended_Blue) #15

Looks like he and I had a very similar approach! I remember theDuckCow from some years ago, back when I programmed Blender/Python as a piano playing robot. He gave compliments to the project.

Thanks for the link!

(Canseco Gpc) #16

This broke a few addons, including built-in ones.

RNA: error on register when classes use invalid identifiers
https://developer.blender.org/rBb24a255ca67841ff2d6121327791e933ce8e3602

So classes without PT, MT, HT, UL , etc, on their name will fail to load the addon.

(Frank) #17

Thanks @CansecoGPC
It sucked early this morning after building Blender but it was an easy fix. :slight_smile:

(chickpea) #18

Hi spydurhank, sorry i Know very little about codeing…many addons show this “doesn’t contain ‘MT’ with prefix & suffix” or PT where & how should i add this…thanks

1 Like
(Frank) #19

Hey chickpea,
I matched my bl idname with my class name.

For a panel:

Class A_PT_panel(bpy.types.Panel):
bl_idname = ‘A_PT_panel’

(Pitiwazou) #20

It’s convention to have the same name for the class and id_name ?

(chickpea) #21

ok i`ll give it a try… thankyou…i really must study the code a bit so as not to feel so helpless!!