Strange 3D cursor location behavior in Add-On

While writing a rather simple add-on to create cylinders based on the built-in add cylinder operator in blender, I came upon a strange phenomenon:
The add-on reads the 3D cursor location and saves them to a variable to place the new cylinder at the obtained coordinates. As soon as I begin to change some settings in the operator properties panel, the coordinates jump to random values in absolutely regular intervals (the random coordinates are also consistent over time). E.g. if I set the vertex count of the cylinder, every third click on the IntProperty panel triggers the jump in coordinates. The object of course jumps to these coordinates, too. The next click resets the location to the correct until the third change, like this:

3D Cursor coordinates: (10, 5, 3)
saved coordinates:1. (10, 5, 3)
2. (10, 5, 3)
3. (0.11412, 0, -14812129141241214214214214124374)
4. (10, 5, 3)
5. (10, 5, 3)
6. (0.11412, 0, -14812129141241214214214214124374)

and so on…

Here is a paraphrased version of the code:



class InnerDiameterCylinder(bpy.types.Operator):#bl_idname and so on go here

#props go here
vertex_get = bpy.props.IntProperty(name = "Vertex Count", description = "", default = 10, min = 1, max = 100)

#define user_cursor_pos variable here to prevent the variable to assume the new cursor position each time changes in the properties are made
user_cursor_pos = (0.0, 0.0, 0.0)

initialized = False

def execute(self, context):

[INDENT=2]if not initialized:[/INDENT]
[INDENT=3]self.user_cursor_pos = bpy.context.scene.cursor_location
self.initialized = True
[/INDENT]
[INDENT=2]bpy.ops.mesh.primitive_cylinder_add(vertices = self.vertex_get, location = self.user_cursor_get)
[/INDENT]

If I just read the cursor location in the execute method directly, this behavior doesn’t happen. The object then follows the 3D cursor to a new (correct and non-random) location. However, I would like to make the behavior as close as possible to the original add cylinder functionality.

Does anyone have a clue about what is going on?

It would help if you’d post the actual non-working code instead of a ‘paraphrased version’ because I see at least two obvious bugs in that code snippet which may or may not be due to ‘paraphrasing errors’.

Sorry about the late reply, but I was busy with other stuff the last days…

By paraphrasing I actually meant leaving out parts like all the other property definitions and registering functions that already worked. But yeah, I also see a paraphrasing mistake: the object location should use self.user_cursor_pos and not self.user_cursor_get.
Apart from that, I guess the way I save the cursor location might be a problem for some reason.

Anyway, I have created a stripped-down version of the script to isolate the problem a little bit better:



2 bl_info = {
  3         "name" : "Add_Test",
  4         "description" : "bla",
  5         "author" : "blub",
  6         "version" : (0, 1),
  7         "blender" : (2, 67, 0),
  8         "location" : "View3D > Add > Mesh",
  9         "category" : "Add Mesh",
 10         }
 11 
 12 import bpy
 13 
 14 class AddTest(bpy.types.Operator):
 15         bl_idname = "object.addtest"
 16         bl_label = "AddTest"
 17         bl_options = {"REGISTER", "UNDO"}
 18 
 19         vset = bpy.props.IntProperty(
 20                                 name = "Vertices",
 21                                 description = "bla",
 22                                 default = 12,
 23                                 min = 1,
 24                                 max = 100)
 25         
 26         user_cursor = (0.0, 0.0, 0.0)
 27         initialized = False
 28         
 29         def execute(self, context):
 30                 if not self.initialized:
 31                         self.user_cursor = bpy.context.scene.cursor_location
 32                         self.initialized = True
 33                 
 34                 bpy.ops.mesh.primitive_cylinder_add(vertices = self.vset, radius = 10, depth = 20, location = self    .user_cursor)
 35                 return {'FINISHED'}
 36 
 37 def menu_func(self, context):
 38         self.layout.operator(AddTest.bl_idname, icon = "MESH_CYLINDER")
 39 
 40 def register():
 41         bpy.utils.register_module(__name__)
 42         bpy.types.INFO_MT_mesh_add.append(menu_func)
 43 
 44 def unregister():
 45         bpy.utils.unregister_module(__name__) 
 46         bpy.types.INFO_MT_mesh_add.remove(menu_func)



The problem is still the same: Whenever I change the vertex count, the object will jump to some random location after a certain amount of changes.

Ok, found a way to achieve this:

I am using the FloatVectorProperty now like this:



92         location_set = bpy.props.FloatVectorProperty(
 93                                 name = "Location",
 94                                 description = "Location for the newly added object",
 95                                 default = (0.0, 0.0, 0.0),
 96                                 min = -1000000.0,
 97                                 max = 1000000.0,
 98                                 soft_min = -10000.0,
 99                                 soft_max = 10000.0,
100                                 step = 1,
101                                 precision = 3,
102                                 subtype = 'TRANSLATION')
103 
116         initialized = False
121 
122         def execute(self, context):
123                 if not self.initialized:
124                         self.location_set = bpy.context.scene.cursor_location
125                         self.initialized = True
126                 if self.polyhole_set:
127                         verts = max(3, ceil(self.radius_set * 2))
128                 else:
129                         verts = self.vertex_set
130                 rad = self.radius_set / cos(pi / verts)
131 
132                 bpy.ops.mesh.primitive_cylinder_add(vertices = verts, radius = rad, depth = self.depth_set, end_fil    l_type = self.cap_set, view_align = self.align_set, location = self.location_set, rotation = self.rotation_set)
133                 return {'FINISHED'}


Which actually makes more sense since now, the behavior of the standard add_cylinder is properly replicated in my modification (location and rotation settings also didn’t work before).