2.80 Cheat Sheet for updating add-ons

(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

???  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'
RuntimeError: Error: Registering panel class: 'view3d.blah' has category 'View'

???  Lamp

???  lamps

***  select (only changed for objects)
-obj.select = False
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")
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

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

???  active
-bpy.context.scene.objects.active = obj
+bpy.context.view_layer.objects.active = obj
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
+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)
-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
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

???  Group

???  groups

???  dupli_group

???  link
+coll = context.view_layer.active_layer_collection.collection

???  link
AttributeError: 'bpy_prop_collection' object has no attribute 'link'

???  unlink

???  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

???  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
-  view_align=False, enter_editmode=False, location=(0, 0, 0)
+  align='WORLD', enter_editmode=False, location=(0, 0, 0)

???  radius

???  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'
AttributeError: 'SpaceView3D' object has no attribute 'transform_orientation'


???  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
"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

???  wm.addon_userpref_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)
TypeError: UILayout.row(): required parameter "align" to be a keyword argument!

***  scene_update_pre

***  scene_update_post

???  scene.update

???  use_occlude_geometry
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", 

???  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

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

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

???  snap_element
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
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

???  register_module
+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')
"LINK",  #  (maybe use DOT, LAYER_ACTIVE or LAYER_USED)

"ALIGN", ??
"BBOX", ??
"DOTSUP", ??
"EDIT", ??
"GAME", ??
"GO_LEFT", ??
"INLINK", ??
"MAN_ROT", ??
"OOPS", ??
"ORTHO", ??
"RADIO", ??
"ROTATE", ??
"SAVE_AS", ??
"SPACE2", ??
Updating Built In Addons to Blender 2.8
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.

(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.


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

o = byp.data.object[0]
    o.hide = False #unhide object using legacy commands
    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

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!!