text:
How can I apply a blur to vertex group weights using python?
It's a long story, but I need to use "Assign Weights" to a mesh in order to get it to export properly into another program.  But the assignment (from the particular rig needed) results in very blocky weighting.  When I use the Blur tool it works great, and the weights are perfect, but I have to do this a few hundred times, on a few dozen bones per mesh, so I was looking for a way to automate it.
I found a couple of scripts that propose to do this, but in the first case it's not a Python script ( https://github.com/assumptionsoup/Blur-Weights ) and I don't know how to run or install Javascript stuff into Blender and in the second case it won't install for me (it runs, but doesn't seem to do anything.
http://linetestjournals.blogspot.com/2010/12/smooth-vertex-group-weights-in-python.html
and the code:
http://pasteall.org/17726/python
The second case seems to contain the code I need, if I strip out all the other stuff that isn't smoothing, but I have zero idea how to get it to run over all vertex groups on the selected mesh.  Does anyone have some help on a stub calling open for the function to do that?  I would be eternally grateful.
Ah, okay, some more info -- I went ahead and finally did get the first script to install (silly me, I wasn't looking in the right place).  It runs, and gives me an error "Outdated internal index table - run ensure_lookup_table() first.
I assume that's a new function that must be called but I'm not sure what parameters to pass to get over this error.  So that's another possibility (and possibly an easier solution than trying to cannibalize the second python script).
Here's all that code:
''' Blurs all weights in the selected vertex group.

This is still one of my first blender addons, so please keep in mind I may be
implementing various operations badly or just plain wrong.'''

'''
*******************************************************************************
    License and Copyright
    Copyright 2012 Jordan Hueckstaedt
    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 3 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, see <http://www.gnu.org/licenses/>.
'''

bl_info = {
    'name': 'Blur Weights',
    'author': 'Jordan Hueckstaedt',
    'version': (1, 0),
    'blender': (2, 63, 0),
    'location': 'View > Weight Tools > Blur',
    'warning': '', # used for warning icon and text in addons panel
    'description': 'Blurs the weights in the selected vertex group.',
    "wiki_url": "",
    "tracker_url": "",
    "support": 'TESTING',
    'category': 'Paint'
}

import bpy
import bmesh
import math
# from mathutils import *

class BlurSettingsCollection(bpy.types.PropertyGroup):
    iterations = bpy.props.IntProperty(
        name = "Iter",
        description = "Iterate this many times",
        default = 1,
        min = 1,
        soft_max = 20)

    factor = bpy.props.FloatProperty(
        name = "Factor",
        description = "Laplace Factor",
        default = 0.5,
        soft_min = 0.0,
        soft_max = 1.0)

    operation = bpy.props.EnumProperty(
        name="Blur Operation",
        items = (('GAUSSIAN', "Gaussian", "Gaussian Blur"),
                ('AVERAGE', "Average", "Simple Average Blur"),
                ),
        )

    blur_type = bpy.props.EnumProperty(
        name="Blur Type",
        items = (('0', "Normal", "Normal Blur"),
                ('1', "Shrink", "Blur will only decrease values"),
                ('2', "Grow", "Blur will only increase values"),
                ),
        )

    selected_only = bpy.props.BoolProperty(
        name = "Selected Only",
        default = False)

class BlurWeights( object ):
    def __init__(self, active_index = None):

        obj = bpy.context.active_object
        if active_index is None:
            active_index = obj.vertex_groups.active_index

        # Get a BMesh representation to access connectivity information
        bm_obj = bmesh.new()
        bm_obj.from_mesh(obj.data)

        # Find face masking.  Faces can only be found in bmesh, however,
        # in paint mode vert selection is not updated correctly to edit mode
        # or in bmesh, so vert selection can only be found through object.data
        # I suspect this is a bug.
        face_mask = obj.data.use_paint_mask
        vertex_mask = obj.data.use_paint_mask_vertex
        if face_mask:
            masked_face_verts = set([v.index for f in bm_obj.faces if f.select for v in f.verts])

        weights = [1.0 for x in range(len(obj.data.vertices))]
        vert_indexes = []
        vert_indexes_test = []
        vert_group_indexes = []
        connected_verts = []
        gaussian_weights = []

        # Convenience function to find group index
        def vert_group_index(vert, group_id):
            for x, group_info in enumerate(vert.groups):
                if group_info.group == group_id:
                    return x
            return None

        # Get weight info.  It's weird, I know
        for vert in obj.data.vertices:
            i = vert_group_index(vert, active_index)
            if i is not None:
                weights[vert.index] = vert.groups[i].weight

                # Skip if vert is not in mask.
                if not vert.hide and (not vertex_mask or vert.select) and (not face_mask or vert.index in masked_face_verts):
                    # Get group info
                    vert_indexes.append(vert.index)
                    vert_group_indexes.append(i)
                else:
                    vert_indexes_test.append(vert.index)

        # Sets are MUCH faster to test in than lists.  This made __init__ run 3x faster for me.
        vert_indexes_test = set(vert_indexes + vert_indexes_test)

        # Only use connected verts in which are in the group.  God this part was a bitch to get working.
        # Also, pre-calculate the guassian weights
        for x in reversed(range(len(vert_indexes))):
            vert = bm_obj.verts[vert_indexes[x]]

            connected_vert = [v.index for edge in vert.link_edges for v in edge.verts if v.index != vert.index and v.index in vert_indexes_test]

            inclusive_verts = connected_vert + [vert.index]
            link_edges = [edge for edge in vert.link_edges if edge.verts[0].index in inclusive_verts and edge.verts[1].index in inclusive_verts]
            if not link_edges:
                # Orphaned vert
                vert_indexes.pop(x)
                vert_group_indexes.pop(x)
            else:
                connected_verts.append(connected_vert)

                # Pre-Calculate gaussian weights.
                avg_edge = sum([edge.calc_length() for edge in link_edges]) / len(link_edges)

                gaussian_weight = {'total_weight' : 0.0}
                for i in connected_vert:
                    distance = (vert.co - bm_obj.verts[i].co).length_squared
                    gaussian_weight[str(i)] = (1.0 /(avg_edge * math.sqrt(2.0 * math.pi))) * math.exp(-(distance)/(2.0 * avg_edge ** 2))
                    gaussian_weight['total_weight'] += gaussian_weight[str(i)]

                gaussian_weights.append( gaussian_weight )

        # The last for loop was iterating in reverse to allow removing indexes while iterating.
        # So these lists are reversed
        gaussian_weights.reverse()
        connected_verts.reverse()

        self.weights = weights
        self.vert_indexes = vert_indexes
        self.vert_group_indexes = vert_group_indexes
        self.connected_verts = connected_verts
        self.gaussian_weights = gaussian_weights
        self.active_index = active_index
        bm_obj.free()

    def execute(self, iterations = 1, factor = 0.5, do_gaussian = True, blur_type = 0, selected_only = False):
        ''' Calculate the blurred weights.
        blur_type options:
        0 - Normal
        1 - Shrink
        2 - Grow
        '''

        # Whatever you do, never save obj to a class member variable.  Blender will freeze.
        obj = bpy.context.active_object

        # Make a copy of weights.  Otherwise edits will be compounded onto the initial weight set.
        weights = self.weights[:]

        for i in range(iterations):
            new_weights = weights
            for x, i in enumerate(self.vert_indexes):
                if not selected_only  or (not do_gaussian and obj.data.vertices[i].select):
                    # Skip guassian if the denominator in the weight function is 0
                    # Which would most likely mean all the connected verts are in the same position
                    if do_gaussian and self.gaussian_weights[x]['total_weight'] > 0.0:
                        average_weight = 0
                        for v in self.connected_verts[x]:
                            average_weight += self.gaussian_weights[x][str(v)] / self.gaussian_weights[x]['total_weight'] * weights[v]
                    else:
                        # average_weight = sum([weights[v] for v in self.connected_verts[x]]) / len(self.connected_verts[x])
                        average_weight = 0
                        num_set = 0
                        for v in self.connected_verts[x]:
                            if not selected_only or obj.data.vertices[v].select:
                                average_weight += weights[v]
                                num_set += 1
                        if num_set:
                            average_weight /= num_set
                        else:
                            continue

                    # Assign new weights with using laplace factor (or can I just call this a lerp? hmmm...)
                    new_weights[i] = factor * average_weight + (1.0 - factor) * weights[i]

                    # Grow or shrink weights.
                    if blur_type == 1:
                        new_weights[i] = min(new_weights[i], self.weights[i])
                    elif blur_type == 2:
                        new_weights[i] = max(new_weights[i], self.weights[i])

            weights = new_weights[:]

        # Update object weights
        for x, i in enumerate(self.vert_indexes):
            obj.data.vertices[i].groups[self.vert_group_indexes[x]].weight = weights[i]
        obj.data.update()

class WeightPaintBlurAll(bpy.types.Operator):
    bl_idname = "object.weightpaint_blur_all"
    bl_label = "Blur"
    bl_options = {'REGISTER', 'UNDO'}

    settings = bpy.props.PointerProperty(type = BlurSettingsCollection)

    active_index = None
    blur = None

    def draw(self, context):
        row = self.layout.row()
        row.prop(self.settings, "iterations", text = "Iter")
        row = self.layout.row()
        row.prop(self.settings, "selected_only")
        # self.layout.prop(self, "factor")
        box = self.layout.box()
        row = box.row()
        row.prop(self.settings, "operation", expand = True)
        box = self.layout.box()
        row = box.row()
        row.prop(self.settings, "blur_type", expand = True)

    @classmethod
    def poll(cls, context):
        obj = context.active_object
        return (obj and obj.mode == 'WEIGHT_PAINT' and obj.type == 'MESH' and len(obj.vertex_groups) > 0)

    def execute(self, context):
        # Lots of addons seem to disable undo during execution.  For whatever reason,
        # I had difficulty with the undo queue reliably being turned back on, so I'm leaving this out.
        # global_undo_state = context.user_preferences.edit.use_global_undo
        # context.user_preferences.edit.use_global_undo = False

        do_gaussian = self.settings.operation == 'GAUSSIAN'

        # Initialize the blur operator if it hasn't been.
        if self.blur is None:
            self.blur = BlurWeights( self.active_index )

        self.blur.execute( iterations = self.settings.iterations,
            factor = self.settings.factor, do_gaussian = do_gaussian,
            blur_type = int(self.settings.blur_type),
            selected_only = self.settings.selected_only)

        # This is a hack.  For some reason the active vertex group changes during execution,
        # Only when used from the Blur PANEL (not the regular blur buttons in the weight paint section)
        # And this seems to happen even when I touch NOTHING related to it (I tried commenting out the
        # blur operation and the active_index query in invoke).  I have...no clue.
        if self.active_index is not None:
            context.active_object.vertex_groups.active_index = self.active_index

        # context.user_preferences.edit.use_global_undo = global_undo_state
        return{'FINISHED'}

    def invoke(self, context, event):
        for key, value in context.scene.weightpaint_blur_all_settings.items():
            self.settings[key] = value
        self.active_index = context.active_object.vertex_groups.active_index
        return self.execute(context)

def panel_func(self, context):
    row = self.layout.row(align = True).split(0.35)
    row.alignment = 'EXPAND'
    row.operator("object.weightpaint_blur_all", text="Blur")
    scn = context.scene
    row.prop(scn.weightpaint_blur_all_settings, "iterations")

def register():
    bpy.utils.register_class(BlurSettingsCollection)
    bpy.utils.register_class(WeightPaintBlurAll)
    bpy.types.Scene.weightpaint_blur_all_settings = bpy.props.PointerProperty(type = BlurSettingsCollection)
    bpy.types.VIEW3D_PT_tools_weightpaint.append(panel_func)

def unregister():
    bpy.utils.unregister_class(WeightPaintBlurAll)
    bpy.types.VIEW3D_PT_tools_weightpaint.remove(panel_func)

    del bpy.types.Scene.weightpaint_blur_all_settings
    bpy.utils.unregister_class(BlurSettingsCollection)
if __name__ == "__main__":
    register()

Ah, nevermind, I found that someone had already posted a fix for this on Github (I'm still a bit unfamiliar with it and didn't look properly.  Sigh).
The fix is to add these particular lines:
if hasattr(bm_obj.verts, "ensure_lookup_table"):
            bm_obj.verts.ensure_lookup_table()

right before you assign the vert to one of the indexes.  Anyway, works fine now.

No, it actually doesn't -- while it "says" it's doing all vertex groups, it only does the active one, and for the life of me I can't figure the code out to make it work properly.  Perhaps I should ask this question again, more clearly.


text:
Extrude symmetrically along an axis
I want to extrude the following two faces symmetrically along the X axis (one to the right and the other to the left):

When selecting only one of the faces and clicking E and then X I get the desired result for that side:

But doing so while selecting both faces drags both of them to the same side:

I have tried Alt+E and then clicking "Extrude Individual faces", but then although symmetrical, it seems I have no control of extruding to a single axis (I tried clicking E after "Extrude Individual faces" but it did nothing):

Is there a way to extrude both faces symmetrically on the X axis?
(I'd wish to avoid cutting the model into a half and then mirror it.)

F3 > Extrude along Normals

I get the same result as with "Extrude Individual Faces", I would like to extrude along the X axis

Extrude one of the faces along the X axis and then select the other face and press Shift+R to do the same. Then press F9 to bring up the pop up window and change the positive X value to the negative
You can also select both and press E+S+X to extrude and immediately scale them along the X axis but you'll have to scale them down individually to for them to have a similar angle as before
Tbh, it's a lot faster for you to use a mirror modifier or symmetrize the mesh by going to mesh->symmetrize

I didn't manage to follow the first option, when selecting the other face should the first face be selected too?
Do I need to extrude the second face as well before the Shift+X?

@Eule No, you extrude the first face along the X axis and then just select only the other face and press Shift+R. (I wrote Shift+x before, that was wrong)

source: Stack Exchange

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/

sort: votes


text:
Select N symmetrical edges in a sphere
If I'd like to select two symmetrical vertical edges in a sphere it is easy to do that manually:

Four would be easy too:

But with other divisions it could be harder to do so manually.
Is there a simple way to select n edges that are covering the sphere with equal distance between each other?

Switch to edit mode, edge select.  Select an edge ring (ctrl alt click on edge for me):

Use a "checker deselect" operation.  Choose a number of selected+deselected that goes evenly into the number of divisions.  The number of times this goes into your divisions will be the number of edges that remain selected.  Set the offset equal to the number deselected:

Use "select/select loops/edge loops" operation:

With 48 divisions, select 1 deselect 3, I have 12 loops selected, although you might see it as 6 loops, since they are continuous across the UV sphere's poles.

A variation on @Nathan's method:

Select one edge, then another, at the desired interval.
Press and hold ShiftCtrlNumpad + ('Select Next Active') to
accumulate selections at the same interval.
Then, as in his method, use Header > Select > Select Loops > Select
Edge Loops.

Do you want to talk about our lord and savior Geometry Nodes?
Go to Geometry Nodes workspace:

Change it to Tool Mode and give it a name Select Symmetric:

Create this simple node setup:

You can do so by first pressing the N key to open the right panel and then add a group input there:

then you can drag from this socket to an empty space, and type the name of the node you see on the screenshot:

Repeat for all other nodes - make sure all values, connections, and options are the same:

Finally, in Edit Mode, press F3 and search for your tool Select Symmetric. Then click in the bottom left corner to expand the settings or press F9 to open the popup. Adjust the settings (for this setup/geometry not all numbers will be valid):

Happy noding!

Thank you! Ahh.. you have a leaflet for me! Great! I shall read it with interest. If you don't mind, at the moment, though, I'm a bit busy.

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/


text:
Blender Python: Fixed size list of elements?
I need 4 instances of a property group sub-class in my primary class, and I want to access them (main.sub[*].x) based on an enum or index.
Here's a fictitious (and boring) example to help illustrate what I'm trying to achieve:
MyTypes = ['A','B','C','D']

class TypeClass(bpy.types.PropertyGroup):
    ... unrelated things in here ....

class MainClass(bpy.types.PropertyGroup):
    States : PropertyGroupList(type=TypeClass,enum=MyTypes)

...
MainObject.States['A'].x = 2

Since there doesn't seem to be a built-in mechanism to construct properties, I'm not sure how I could achieve this with a CollectionProperty, unless I defined my own handler to generate the 4 elements. I have zero experience in dealing with python lists or arrays, other than defining empty lists and iterating/adding/removing. Any advice is appreciated.
Edit: (more than once)
This is the best way I've found to do this so far, and it has little to do with lists:
from enum import Enum

class ThingTypes(Enum):
    A = 0
    B = 1
    C = 2
    D = 3

class MainClass(bpy.types.PropertyGroup):

    # data for each mode
    ModeA : PointerProperty(type = TypeClass)
    ModeB : PointerProperty(type = TypeClass)
    ModeC : PointerProperty(type = TypeClass)
    ModeD : PointerProperty(type = TypeClass)

    # access mode based on enum index
    def Mode(self,type_index):
        if type_index == ThingTypes.A:
            return self.ModeA
        elif type_index == ThingTypes.B:
            return self.ModeB
        elif type_index == ThingTypes.C:
            return self.ModeC
        elif type_index == ThingTypes.D:
            return self.ModeD
        else:
            raise Exception("Invalid mode")

... usage ...

MainObject.Mode(ThingTypes.C).Attribute = 0

If there is a better way, I'm interested to find it. Preferably some way to actually define the sub-class instances as a list, then just access the list using the enum/index. Thanks for any info.

In my project, I've switched most of the data in the add-on to use lists, and access those with a type index, which is great because I've divided most of my code by 4. But I still haven't found any way to do this inside of a class derived from PropertyGroup. When I try to define anything as a list inside of the class, something breaks down in the Blender pipeline. I'm still relying on the if-else grab function at the moment. My guess is there is no other way to pull this off.


text:
How can I detect when the active or selected object changes using Python?
Is it possible to detect changes in object and collection selections or activations (bpy.context.object/collection)? I'm most interested in detecting changes in the active object and active collection.
If there currently is no way to receive events for selection or active object changes, what is best practice for setting up a looping processing function for an add-on? Would I need to add some type of timer? Or is there a handler that would work good for this?
My intention is to figure out which type of object was activated most recently - a collection or an object, so I can draw controls that relate to that object type. I'm currently just drawing both, but it takes up a lot of space.
Is there possibly some type of "activation_time_stamp"? Or anything that would help?

Is there anything stopping you from checking what the selected object is in the draw function of the panel? That function is executed whenever the UI is drawn, therefore you don't need another callback or handler.

I can figure out what is active and what is selected, but I have no way of knowing which one the user activated last. So if I have different controls to manipulate both collections and objects, but I only want to show one of those sets of controls at a given time, I have no way of knowing which the user is wanting to manipulate (collection or object). Unless there is a state somewhere that one could use as a hint, like a previous active object state. That's what I was trying to incorporate, but I would need some type of processing loop to do so.

Then that's a design problem of your add-on. There is nothing wrong with adding two sub-panels one for the active object and one for the active collection. This gives the user the option to collapse the sub-panel if it's not needed. Trying to create a handler that monitors every selection change just to hide a panel doesn't sound like a good idea.

Right, that's what I have now. I was just hoping to make it cleaner/simpler by showing options for whatever the user is dealing with at the moment. Collapsing panels wouldn't be ideal in this situation because the user would likely be constantly switching between the two types of objects. But I doubt I will create a processing function or timer just to make it happen, because even with the timer, it would feel like a hack. Perhaps there is some way to detect the "active outliner item"? That would be ideal.


text:
Blender Python: Detect Collection Exclusion Checkbox?
Is there any way to logically check the state of each collection's primary checkbox (the one to the left of its name in the outliner)?
When the box is toggled, the info panel shows "bpy.context.scene.exclude = True/False", but that doesn't make sense, since it is a collection being excluded, not the entire scene? Also, there doesn't appear to be any "exclude" member mentioned for collections in the docs.
When one of these are disabled, some exporters avoid exporting their objects, which is useful. But I believe they are pulling this off by selecting ALL objects, which excludes any in unchecked collections.
Does anyone know how to read this value correctly?
Edit: There is a similar question here
How can I exclude a collection from rendering with Python?
And the answers to this question also answer this question, but the questions are not the same. The checkbox in question is not specific to rendering. It excludes the object from the view layer (view-port, selections, etc). In addition, there is a specific toggle for render exclusion at LayerCol.Collection.hide_render.

The exclude property is what you want right? See: How can I exclude a collection from rendering with Python?

It looks like it. But when I try to access collection.exclude, I get an error:
"AttributeError: 'Collection' object has no attribute 'exclude'" ... I also cannot find exclude in the 2.8 docs. Maybe there is a version difference? Or possibly because I'm confusing two types? My collection reference comes from the bpy.context.scene.collection.children list.

Looks like I need to use bpy.context.view_layer.layer_collection and iterate its children instead of the scene's master collection. Is that right? I didn't even realize LayerCollection existed until now.

Yes, it worked. Thank you again for your help. The other question is titled as "from rendering", and there is a specific toggle for render exclusion. which makes it appear unrelated. This checkbox excludes it from the view-port, from selections, etc. It excludes it from pretty much everything.


text:
why does my mesh glitch out like this while moving in edit mode?
these are pictures of my mesh before and after I move it
does anybody know how to fix it?

Hello, could you please share your file? https://blend-exchange.com/

Disable Mesh symmetry XYZ ... top-right row next to a butterfly icon.


text:
Geometry node : move curve's endpoint along tangent
I'm trying to move a curve's endpoint outwards along its tangent with geometry node, do you think it's possible?
pretty much like this

thank you

Set Position selected with Endpoint Selection feeded with Curve Tangent scaled by $X$?

Yes it was actually this simple. I was trying to get the curve tangent with the capture atribute node and it wouldn't work. Thank you

Does one of you fancy posting the solution in the comment as a quick little  answer? Or shall we wind the question up? I would do it myself, but don't want to intrude :)

@RobinBetts I just did post an answer

@Alex Cheers! After a while, you can accept it, too.

I was able to get it to work thanks to @quellenform with this simple setup :

The scale value will move the curve's endpoint along its tangent


text:
Geometry Node snap points on grid
I've ran into a problem when using the new "Distribute points in volume" node in geometry node set with the grid distrubution method: the points are not aligned properly with the scene units. I can't figure out how to make it happen. Any help is welcome
Here is how it looks

All points are offset on all 3 axis

I don't know if there's any particular reason why they would conform to the grid, it probably gives precedence to the shape and size of the mesh, but if you want to, you can use a Vector Math in Snap mode to, well, snap their positions to increments of your choosing. If you choose a wider increment than the original grid you would end up with multiple points at the same positions so you might wanna use a Merge by Distance afterwards to get rid of unnecessary geometry.

Thank you this is perfect. I had placed a geometry to instance node right before the Set position which didn't allow me to snap the points for some reason. Thanks again

@Alex When you turn a geometry into an instance, at the moment of its creation its 'origin' is set at [0,0,0], so if you then try to "snap" its position nothing will change since [0,0,0] is already on the grid.

I see, thank you for clarifying


text:
Geometry nodes Flatten by average normals
I am trying to use geometry nodes to flatten the mesh by the average normals, kinda like looptool's flatten option. But I have two issues : The first one, the mesh rotates by 90 degrees. The second one, there is an offset. I figured both issues could be linked, but I have no idea why it happens

did u just try to use blur?

@Chris No I haven't tried, where would I use it?

like this:  [1]: https://i.sstatic.net/LXcDK.gif

thank you, however i wont be able to get the result I'm looking for with this method since it breaks the original shape. This behaves more like a smooth modifier

Do you want something like this?

It uses vector projection to move all points to the mean normal axis and then calculates the offset from the mean position also projected to the mean normal axis.

Thank you, this is exactly what I was trying to achieve


text:
Geometry nodes face count per instances
I'm trying to make a geometry node setup that displays the face count of each object of a collection, but I can get it to retrieve the count for each individual objects (it only displays the total). Is there a way to do this? I tried using the mesh island node without much succes unfortuanetly

I'm very sorry for you, but this doesn't work structurally the way you set it up. First, the node Attribute Statistic always returns a value that refers to the whole geometry (you would have to work with Accumulate Field instead), and second, the instances will always look the same, because an instance is a duplicate of an object. You would have to create and position the numbers dynamically instead.

I see, I had a feeling I wasn't doing it the right way

Hi, @quellenform.. can you think of a clean way of storing number of  (realized) faces per instance on original instances? the only way I've found is a scale-to-0 and merge hack.. maybe I should post this q  as one of my own.

@RobinBetts ...maybe this one? https://i.sstatic.net/EyHw3.png

@quellenform .. OK,  a bit less grubby than mine :) (I scaled realized instances to merged points and sampled those) I thought there might be a many-to-one indexing trick I hadn't grasped.. it's reassuring your method is similar.

It is now possible to get the face count of each instance using the repeat zone


text:
Use built-in object modes enum?
Is there any way to directly use Blender's object mode enum? Rather than having to "hard code" our own?
ActiveModes : EnumProperty(
    name = "Active Modes",
    options = {'ENUM_FLAG'},
    items = bpy.types.Object.mode,
    description = "x",
    default = {'OBJECT','POSE','SCULPT'},
    )

items = bpy.types.Object.mode is not valid.
I'm referring to this enum described in the 2.8 docs:
enum in [‘OBJECT’, ‘EDIT’, ‘POSE’, ‘SCULPT’, ‘VERTEX_PAINT’, ‘WEIGHT_PAINT’,
‘TEXTURE_PAINT’, ‘PARTICLE_EDIT’, ‘EDIT_GPENCIL’, ‘SCULPT_GPENCIL’,
‘PAINT_GPENCIL’, ‘WEIGHT_GPENCIL’], default ‘OBJECT’

Does anyone know of a way to access these items to reuse them?
Edit: I was able to find what I think is the definition of this list in Blender's source. If someone can some how use this to locate the python version, that would be great. Otherwise, if nothing else, at least it gives us quick access to the accurate display name strings:
const EnumPropertyItem rna_enum_workspace_object_mode_items[] = {
    {OB_MODE_OBJECT, "OBJECT", ICON_OBJECT_DATAMODE, "Object Mode", ""},
    {OB_MODE_EDIT, "EDIT", ICON_EDITMODE_HLT, "Edit Mode", ""},
    {OB_MODE_POSE, "POSE", ICON_POSE_HLT, "Pose Mode", ""},
    {OB_MODE_SCULPT, "SCULPT", ICON_SCULPTMODE_HLT, "Sculpt Mode", ""},
    {OB_MODE_VERTEX_PAINT, "VERTEX_PAINT", ICON_VPAINT_HLT, "Vertex Paint", ""},
    {OB_MODE_WEIGHT_PAINT, "WEIGHT_PAINT", ICON_WPAINT_HLT, "Weight Paint", ""},
    {OB_MODE_TEXTURE_PAINT, "TEXTURE_PAINT", ICON_TPAINT_HLT, "Texture Paint", ""},
    {OB_MODE_PARTICLE_EDIT, "PARTICLE_EDIT", ICON_PARTICLEMODE, "Particle Edit", ""},
    {OB_MODE_EDIT_GPENCIL, "EDIT_GPENCIL", ICON_EDITMODE_HLT, "Grease Pencil Edit Mode", "Edit Grease Pencil Strokes"},
    {OB_MODE_SCULPT_GPENCIL, "SCULPT_GPENCIL", ICON_SCULPTMODE_HLT, "Grease Pencil Sculpt Mode", "Sculpt Grease Pencil Strokes"},
    {OB_MODE_PAINT_GPENCIL, "PAINT_GPENCIL", ICON_GREASEPENCIL, "Grease Pencil Draw", "Paint Grease Pencil Strokes"},
    {OB_MODE_WEIGHT_GPENCIL, "WEIGHT_GPENCIL", ICON_WPAINT_HLT, "Grease Pencil Weight Paint", "Grease Pencil Weight Paint Strokes"},
    {0, NULL, 0, NULL, NULL},
};

In case it matters, there is also another list/version, named rna_enum_object_mode_items that has slightly different mode names for Grease Pencil modes.


text:
Object Stack Collapse
It makes a lot of sense to keep copied (arrayed or mirrored) objects around without collapsing the modifier stack for as long as possible. It allows you to make subtle changes to the root objects and have it influence all of the copies.
Preferably, I would rather never collapse the modifier stack. And it seems like I'm close to pulling this off, except for two big issues..
1. UV editing - Is it possible to layout UVs for a larger object when it consists of multiple element objects that are mirrored or array duplicated? I'm wanting each copy to have its own surface area.
The UV "offset" values within the Mirror/Array modifiers work great, but its difficult to group multiple objects using array modifiers into a single UV map area without collapsing their modifiers. How do you guys deal with this? Is there some way (similar to Max) to add additional modifiers to manipulate UVs on top of the array modifiers? Or is there a way to preview these modifier end results inside the UV editor?
2. Combining into Larger Objects and/or Exporting - Within my game resources, I would prefer many small objects be collapsed down into their single respective larger objects. In order to leave the array modifier active on smaller components, I cannot combine them into their larger objects. So to avoid collapsing the modifiers, I have to leave all of these smaller objects separated. This means I have to join all of them together before exporting, which can become quite a task. Is there an easy way to get this to happen?
Something that seems like it would be useful would be a plugin that automatically combines associated objects, based on a name suffix or through some type of static mesh parenting. Either right before export, or through some single command execution that can be undone in one go.
Anyone else facing these problems and found solutions?
Thanks!

I found something helpful to deal with the modifier stack issue when dealing with UVs (issue #1). Inside of the UV editor, under the [N] key panel, within the "View" tab, under "Overlays", there is a checkbox called "Modified" which shows the end result of modifiers.
So if you use the "offset" features of the array and mirror modifiers, the duplicated geometry will show up in the UV editor as faded gray lines. Extremely helpful!
Seems like this box should be checked by default.
So the thing I'm most concerned with is dealing with multiple sub-objects of simple larger objects. When those sub-objects have modifiers applied to them. It would be great to have some way to combine these together automatically or quickly for exporting.


text:
How can I create a menu with python that toggles seperate objects visibility?
import bpy

class EXAMPLE_PT_panel(bpy.types.Panel):
    bl_label = "Test Rig"
    bl_category = "Rig Options"
    bl_space_type = "VIEW_3D"
    bl_region_type = "UI"

    def draw(self, context):
        layout = self.layout

        layout.label(text="Collection 1")
        layout.operator(bpy.data.objects["Jeans"].hide = True)

        laout.label(text=Collection 2")
        layout.operator(bpy.data.objects["Jacket"].hide = True)

classes = (EXAMPLE_PT_panel,)

def register():
    for cls in classes:
        bpy.utils.register_class(cls)

def unregister():
    for cls in classes:
        bpy.utils.unregister_class(cls)

if __name__ == "__main__":
    register()

I'm learning python and want to try and make a simple menu that allows a user to click 1 object in menu and have the others hidden until chosen.
For example
select value 1, values 2-5 are hidden.
select value 3, values 1-2, 4-5 are hidden

Hi. Where specifically are you getting stuck? Please show the code you have so far so we know what exactly you need help with.

Hi @RayMairlot, I have edited the post to include an image. I feel like I should be using if commands.

Hello. For that, should be better to paste the code directly instead of image. If someone wants to answer, he won't need to rewrite all... thanks.

There are a lot of examples  including this from here; among numerous others, ,  addon code, UI code or in the script  templates.  Much of  this code is in your blender installation folder and can be investigated with any text editor. Suggest will not find anything like layout.operator(bpy.data.collections["Foo"].hide_viewport = True) in any working blender panel or menu code.


text:
Rig model with existing armature
I imported a model from a game that already has it's own weighted armature.
I was wondering if there is away to use that armature to rig the model to use in Blender.
I've spent quite a long time looking up how to do but, I haven't been able to find a answer.

Please add some more infos or share the .blend file: which format did you use for import? Is the rig working badly or not working at all?, etc.....

It was imported as a .fbx from 3dsmax and like I said the armature is already weighted. I just can't figure out how to rig it without completely remaking the armature

So in short, you have a "deform rig" and you would like to combine it with a complete rig like rigify (which includes its own deform rig, controllers rig, mechanical rig, ...)?
Sadly it isn't possible. Not in an automated way I mean. You can't mix two different rigs and expect them to work together, they don't know how to "communicate" with each other.
But you have different options to choose from:

Start from the original deform rig and manually build your own controls and mechanics around.
Discard the original deform rig and create a whole new one with rigify.
Try to rename the meshes's vertex groups to the corresponding rigify's deform bones so that the rigify rig uses the original vertex groups for deformation, and make some adaptations when needed.

There isn't one best solution IMHO, they each have their pros and cons. But depending on your situation and goals, some might be more adapted.
If you just want to have an animation ready rig as soon as possible and you feel comfortable with retargeting weights, then the third option looks fine.
If you want your rig asap but don't quite enjoy the tricks of retargeting, then the second option looks more appropriate.
If you want to learn how to rig and skin, then the first option is hand on the best. Or even start from scratch, it's even more instructive.
If you know how to rig, then... Well, whatever, really.

The rig is working.
Just go to object mode, select the rig, go to pose mode, select a bone and move it.

What about with rigify? I thought that was the rig. Everytime I try rigify on the armature... it generates a rig but, not correctly.
I'm sorry if I'm doing it wrong. I'm still very new to using Blender.

In order to use Rigify you should delete the old rig, add an human metarig, in edit mode adapt the bones to stay in the appropriate position in relation with your model, then click "Create rig" in the armature properties panel: hide or delete the metarig, select the model, shift select the new rig, press Ctrl P choosing the "Automatic weight" option. The Rigify rig is way more a better rig than the existing one (but it's also more complex).


text:
How to attach parts of one model to another
i have a 3d model, i want to swap it's feet and head with another 3d model.
i imported both models, selected the parts, moved them to the desired position, pressed control + j to merge them.
but now it looks weird, it's so obvious that the feet doesn't belong to this body

i tried to fix this in sculpt mode but ended up making it look worse, so sculpting is either a wrong tool for this situation or i don't know how to use it currently.
can someone Please help me fix this problem?
thank you

please share your file, I guess you can delete some edge loops on the foot and use some topology tricks

@moonboots Hello, i actually don't know about edge loops and topology but here's my file
thank you

In your case you can delete a lot of useless edge loops on your foot, you'll have the amount of vertices that will allow you to make the joint with your leg. As long as you choose the good edges it won't affect the shape of your foot. To do so you'll have to dissolve some edges, use the knife to create some edges between vertices, and at last merge the vertices of foot and leg. And don't forget to delete the face on the bottom of your leg.

i followed the steps, and fixed my problem, thank you so much ♥


text:
Modal Operators: Click Object Event
I'm currently working on a python tool using a modal operator.
Now I know to finish the operation I can use:
if event.type == 'LEFTMOUSE':
    return {'FINISHED'}

However it seems not to count as a 'LEFTMOUSE' when I click (select) an object! I also tried 'SELECTMOUSE' which doesn't do anything.
What I would like to do is store the clicked object, and then automatically finish the modal operator.
Any ideas? Thanks in advance!

I have a solution and it's actually very simple:
class OBJECT_OT_do_stuff(bpy.types.Operator):
    bl_idname = "object.do_stuff"
    bl_label = "Do Stuff"

    origSel: None

    @classmethod
    def poll(cls, context):
        return context.active_object is not None

    def modal(self, context, event):
        # Update selection
        curSel = context.selected_objects[-1]

        # On selecting new object
        if curSel is not self.origSel:
            print("selection was changed")
            return {'FINISHED'}

        elif event.type in {'RIGHTMOUSE', 'ESC'}:
            print("cancelled operation")
            return {'CANCELLED'}

        else:
            return {'PASS_THROUGH'}

        return {'RUNNING_MODAL'}

    def invoke(self, context, event):
        self.origSel = context.object
        # Execute Modal Operation
        context.window_manager.modal_handler_add(self)
        return {'RUNNING_MODAL'}

I assigned an attribute that in the invoke function gets filled with the active object. Then the modal function keeps comparing the current selection to the previous one!
An important thing to note is that in order for that to work you need to call the function with the invoke argument :bpy.ops.object.do_stuff('INVOKE_DEFAULT')

Using the last in the selected list could make this a little random,  Would use curSel = context.object

You're right, thanks

Why type.event ?
You should get your event.type, and you may want to compare the event.value as well:
def modal(self, context, event):
    if event.type in {"LEFTMOUSE"} and event.value == "RELEASE":
        return {'FINISHED'}
    return {'PASS_THROUGH'}

Also, it might be possible that an event been stop propagate in most of the event handling system. You might need to check the context carefully to see what is the main problem.

sorry I actually meant event.type and also got that right in my script.
when I use the value RELEASE, clicking an object does end the modal but therefore doesn't select the object...

So you want to check something after you click and select an object? I don't know if it is safe to do relative thing in a same event loop. Interesting problem, I will test a little bit for it.

Great script.
I arranged it so that it responds even when not selected.
import bpy

class OBJECT_OT_do_stuff(bpy.types.Operator):
    bl_idname = "object.do_stuff"
    bl_label = "Do Stuff"

    origSel: None

    @classmethod
    def poll(cls, context):
        return context.active_object is not None

    def modal(self, context, event):
        # Update selection
        selobj=context.selected_objects

        if selobj != []:
            curSel = selobj[-1]
        else:
            return {'PASS_THROUGH'}

        # On selecting new object
        if curSel is not self.origSel:
            self.report({'INFO'}, "selection was '{}' changed".format(curSel.name))
            return {'FINISHED'}

        elif event.type in {'RIGHTMOUSE', 'ESC'}:
            self.report({'INFO'}, "cancelled operation '{}'".format(curSel.name))
            return {'CANCELLED'}

        else:
            return {'PASS_THROUGH'}

        return {'RUNNING_MODAL'}

    def invoke(self, context, event):
        self.origSel = context.object
        # Execute Modal Operation
        context.window_manager.modal_handler_add(self)
        return {'RUNNING_MODAL'}

classes = (
    OBJECT_OT_do_stuff,

    )
def register():
    for cls in classes:
        bpy.utils.register_class(cls)

def unregister():
    for cls in classes:
        bpy.utils.unregister_class(cls)

if __name__ == "__main__":
    register()


text:
vertices are not selected properly, and i cant recalculate normals
vertices,face dots are not selected properly, and also i cant recalculate normals.this is an appended model from a file edited in b3d 2.81, which i need to use it in b3d 2.79b because the game engine, then i got this problem, someones know to fix it? i have seen this before happening when appending a model from 2.79b to 2.80/2.81

please share your file: https://blend-exchange.giantcowfilms.com/

@moonboots here you go

guysss help meeee

I don't see what's the problem, could you please describe more precisely? I can select faces or vertices, flip normals, etc... there might be som weight problem here and there though.

@moonboots is in the mesh the problem as i said the vertices looks selected like in the upper capture, they usually look like that, see face mode and you will see the dots only selected, if no i dont know whats happening then, but as i said this model was appended to 2.79 from a file created from b3d 2.81...i recalculate the normal and does nothing in the black sided faces, but if i select those faces and click in flip normal its get fixed but is not normal that i have to select them individually to fix it.

Maybe what you're talking about is only a problem of mesh display: In the 3D View, press N to display the right panel, then in the Mesh Display panel, enable Faces, Edges and Crease as it is supposed by default? In 2.8 it will be in the header menu > Viewport Overlays panel.

damn thank you i didnt realize that!


text:
(Video Included) Addon Wont Activate after Installation
I'm trying to enable an addon from a basic python template I saved, but it wont let me check the box to activate it. Here's what the problem looks like:
https://www.youtube.com/watch?v=tGFOwwfikAA&feature=youtu.be
Is there any reason it's not letting me do this?
Thank you very much for your time!
import bpy

def main(context):
    for ob in context.scene.objects:
        print(ob)

class SimpleOperator(bpy.types.Operator):
    """Tooltip"""
    bl_idname = "object.simple_operator"
    bl_label = "Simple Object Operator"

    @classmethod
    def poll(cls, context):
        return context.active_object is not None

    def execute(self, context):
        main(context)
        return {'FINISHED'}

bpy.ops.transform.translate(value=(0, 2.20362, 0), orient_type='GLOBAL', orient_matrix=((1, 0, 0), (0, 1, 0), (0, 0, 1)), orient_matrix_type='GLOBAL', constraint_axis=(False, True, False), mirror=True, proportional='DISABLED', proportional_edit_falloff='SMOOTH', proportional_size=1, release_confirm=True)

def register():
    bpy.utils.register_class(SimpleOperator)

def unregister():
    bpy.utils.unregister_class(SimpleOperator)

if __name__ == "__main__":
    register()

    # test call
    bpy.ops.object.simple_operator()

Can you include the code or at least the module registration code in your Question? The error message indicates there is a context mismatch i.e. you are doing something in the registration of the module that you should not be.

Sorry for the ugly formatting. I can't seem to figure out how to put the code in proper format from the 'add-comment' button. Here is the code again by itself.

bpy.ops.transform.translate(value=(0, -3.05949, 0), orient_type='GLOBAL', orient_matrix=((1, 0, 0), (0, 1, 0), (0, 0, 1)), orient_matrix_type='GLOBAL', constraint_axis=(False, True, False), mirror=True, proportional='DISABLED', proportional_edit_falloff='SMOOTH', proportional_size=1, release_confirm=True)

It's just code I got from the info window to move the cube left a bit.

Can you upload the Python file to a pastebin. I really sounds like you have not put the code in the its own function and are instead running it from the module registration which is only supposed to tell Bender it is there.

Sure, how do I upload a file to the pastebin though?? Sorry, I'm still getting the hang of this forum.

Edit your original question and paste in your Python then select what you have added and click the button with the two curly braces, this will format the display as code. pastebin.com is a free web site where you can paste in code and have it formatted, all without having to signup

I tried to do that. Almost worked. It only put some of the code in proper format though. It's just a "simple operator" template, with cube movement code pasted from the info window under the line that says "return finished"

You have put your operational code in as part of the Class SimpleOperator.
This means that when the register creates the Class your code is run, which is the wrong time and has no context.
Take the bpy.ops.transform.translate code and move it out of the Class definition and move it into the main function e.g.
def main(context):
    for ob in context.scene.objects:
        print(ob)
    bpy.ops.transform.translate(value=(0, 2.20362, 0), orient_type='GLOBAL', orient_matrix=((1, 0, 0), (0, 1, 0), (0, 0, 1)), orient_matrix_type='GLOBAL', constraint_axis=(False, True, False), mirror=True, proportional='DISABLED', proportional_edit_falloff='SMOOTH', proportional_size=1, release_confirm=True)

Now when you run the test call
bpy.ops.object.simple_operator()

It will print out all the Object names and then try and Translate the currently selected Object

Worth noting, can ditch the main method all together and simply return bpy.ops.transform.translate(...) as a one line execute method.  Also the naming convention for 2.8x would suggest this class  be defined as  class OBJECT_OT_simple_operator(...)


text:
2.80 Make the data single user. Like pressing U key in blender 2.79
In 2.79 I could press U to make data single user.  How can I do this in 2.80, what is the hotkey?

From menu Object - Relations - Make single user

One way to do restore the functionality to a hotkey is to add a custom keymap in Preferences. I added one under 3D View > 3D View (Global) with object.make_single_user as the function and Selected Objects for Type.

It seemed to work ok, but it doesn't bring up the context menu like before. The options appear in the small window at the bottom of the screen, usually collapsed by default. Or if you always want to perform the action on data, I think you can pre-check that Object Data box in the keymap settings and bypass the context box entirely.
If you want to keep the modal context menu with a hotkey though, you can right-click the Make Single User menu item (under Object > Relations) and add it to your Quick Favorites menu (Q).


text:
extend edge crease with extrusions in geometry nodes
is there a way I can extend the edge crease to the adjacent edge when using the extrude node in geometry nodes?
This is what I curently have (left), this is what I get when I apply the modifier (center) and this is what I'd like to have (right)

I don't know if maybe there's a Blender 4 easy way to do it, but in the past... Geometry Nodes: set sharp or crease attribute for an edge

@MarkusvonBroady I'll try to look more into it, but rn I still can't do it right

The trick is writing sharp attribute into vertices, then read back from vertices to edges:

This requires using topology nodes. Edges of vertex so that we know that the vertex is connected to a sharp edge. And Edge vertices, both of vertices is from sharp edge.

Thank you, works very well. However I noticed the node setup works better if the last math node is switched to minimum rather than multiply that causes flickering in some cases. Also, why is the subtract node needed before the edge of vertex node?

Yes, if you look at image I've made an update and replace multiply by minimum. Subtract is used to reverse the order (maximum value goes first).

The Geometry Node modifier for this problem can be simplified to:

Instead of storing the crease_edge attribute in its native Edge domain we temporarily store it in the Vertex domain as a Boolean type.
Thus with every extrusion the extruded copy of the vertices will inherit their Boolean values from the previous iteration.

If the crease_edge attribute was stored in the Edge domain the newly generated Edges that are not copies of the previous mesh will not inherit any value, thus forming a gap in the edge loop.

(note that the highlighted edge in the first iteration is not selected, it is just difficult to visualize the Boolean Edge selection with the Viewer Node, so the display in the animated images is set to Point)
After the Repeat Zone  the crease_edge attribute is stored back in  the Edge domain as a Float type. To make sure the interpolation to Float values is done without including "half selected edges" we pass the attribute though Evaluate on Domain node set to type Boolean in Point domain. This will select only edges which have both of their vertices selected.
Optionally - after the Evaluate on Domain node you can include a Multiply node to change the value of the edge crease if needed.

Another possibility: use of shortest edge paths after the loop.

Capture edge crease attribute of the original edges (either on edge or point domains).
Use it as end points selection for the shortest edge paths node.
Use the crease as start point on the resulting mesh.
Set the crease_edge attribute to the value for the edges selected by shortest paths.

Note: the issue to go throught point domain, instead of edges, is that you'll propagate crease along other parts of the mesh if there is several creases in the base mesh/surface.
For instance:

And this is not the case using shortest paths because all is done in edge domain concerning the creases:

Other point: if you want to report the (mean) crease of the original surface (instead of a constant value), you can add these nodes:

That is very clever, I didn't think of using shortest edge path. I was able to get rid of the propagated creases by removing the side loops from the selection but this is a much simpler solution

Strangely, this does not work if you invert "end" and "start" vertices. I don't really know why but I suppose this is because end vertices are to be in a separated (because captured) data.


text:
Align vertices in geometry nodes
I'd like to make a geometry nodes setup that allows me to align a set of vertices between two points. I'd like to avoid using a curve or mesh line starting from a point and ending to another since I want the node setup to work with 4.0 node tools. I've been trying for quite some time now and can't figure out anything convincing. Any help is appreciated, thank you

I haven't done a lot with 4.0 so far, pardon my stupid question: curve or mesh lines are not working in 4.0?

@GordonBrinkmann They do work in 4.0, however this is not helpful when making a node tool which purpose is to deform or move the selected geometry since it wont be able to replace it (when there are faces connected to that selection for example). There could be a way to use them with geometry proximity but this is very sketchy and wont work very well

Not sure if this is what you want...

This is exaclty what I was looking for, thank you. Now I'm going to try to space the points evenly. Thanks again


text:
Fast Loop Cut in 2.8
I found a video @ https://www.linkedin.com/learning/blender-tips-tricks-and-techniques/use-the-mesh-edit-tools-add-on (see video at time 2:02) that shows a really nice loop cutting tool called "Fast Loop" (NOTE: see edit at bottom of this post - this tool doesn't do what I originally thought).
The addon is called "Mesh edit tools 2", and the video author mentions it ships with 2.79. I have 2.8, which has "Mesh Edit Tools" included, but no mention of "#2", and I don't see this really useful loop cutting tool anywhere.
Does anyone know anything about this? Is this version available for Blender 2.8? Or is this fast loop tool still available in the version that exists now?
If anyone is having trouble seeing the tool in the video, it essentially allows you to skip the loop slide part of creating a loop. The loop is instantly created wherever your mouse is. So you can literally click, click, click. Seems like this would be a really nice feature. Especially on those very long edges where you can't even see where your loop is being created until you slide it some distance.
If there is some way to pull off something similar in 2.8, that would be great too.
Edit: After watching the video more closely, it appears this addon did not instantly create loops where the mouse is hovering. The gentleman in the video is actually sliding loops by holding down the mouse button.
So I'm looking for something that may not exist at all. A loop cutting tool that instantly slides to where the mouse is hovering. Imagine a situation like this one..

So the user cannot see the center of the box they are adding a loop to because they are zoomed in too close. This happens often when working on longer low poly models like boards and sticks. In order to create a loop cut where the orange edge loop is, the user must create it off-screen, and very slowly (because the slide factor resolution increases as you zoom closer) slide it over into view. What I'm hoping for is a way (addon or feature) to instantly create a loop exactly where the mouse is hovering. So there would be no sliding involved. The preview would show the user where the loop will be cut, so there would never be a need to slide them.
Anyone know if something like this is possible? Any idea how difficult it would be to write a tool like this? I know very little about Python, but I have C++ programming experience. Seems like the hardest aspect of creating something like this would probably be calculating the slide factor based on the mouse cursor location.
Thanks again for any help!

You actually don't need any addon for it in 2.8. You just select Loop Cut on the left side bar and each time you click, new loop cut appears. Then you can hold down the mouse button to slide new loop but as a default it stays in place and you can keep clicking and adding loops.

Right, but that is the normal loop cut, right? Where it creates the loop in the exact center of the edges where the mesh is hovered/clicked? If I'm not mistaken, the "Fast Loop" version (in the video) previews and creates the loop exactly where the mouse is hovered, so the user doesn't need to slide it at all to get it where they want it.

You know what - after watching it again, he may be holding down the button to slide loops. I was under the impression that it was showing a preview of where the loop will be created when they were moving around, but it may be normal sliding.


text:
Blender Python: Selections and Context
I'm trying to understand how selections and active objects work within a context. I  thought I understood that a selection is part of a context. I read somewhere that you can create a copy of a context (context.copy()) in order to avoid changing the user's actual selections.
Some code I've seen fits this concept, such as..

context['selected_objects'] = list
context['active_object'] = object

But other code I've seen does not, such as..

object.select = False
bpy.ops.object.select_all(action='DESELECT')

Would anyone be able to help me understand what's happening behind the scenes? I can't imagine how object.select = False can be triggering any state changes inside of a context? Perhaps objects have their own selection states, but they can be overridden by a context? Or maybe the things I read were completely wrong?
Thanks!
Edit: It appears that part of my issue is that Blender keeps changing the syntax and setup of how selections work. It looks like they are now part of the view layer. But if I make a copy of the context, Blender reports that it doesn't even have a view layer. Does anyone know how to properly copy the context and select/activate objects with the copy?

In Blender 2.80 and after obj.select = Bool is replaced by obj.select_get() and obj.select_set(). Context should track all change inside it, I guess

Any idea how a copied context (I keep seeing it called an "override") can be used in this situation to avoid changing user selections? Blender's context has a view layer at bpy.context.view_layer. But if I copy the context with copy= bpy.context.copy(), my copy does not seem to have a view layer at copy.view_layer. Can anyone help me understand why? Or just how to use a context override correctly?

Don't. You only need to copy the context in case you want to override the actual context of an operator call like bpy.ops.object.delete({"selected_objects": objs}), good read: poll() failed, context incorrect?. Otherwise all operator methods already provide the current context (default argument): def execute(self, context): so don't worry about that too much. More about selection in 2.8 here: Python: Selecting object by name in 2.8

Ok, got it. Thanks. My only intention was to avoid changing the user's states like current selections and active object. Most of the add-ons that come shipped with Blender seem to be doing this manually, so I assume that is the best way? Just back them up, change them, execute functions, and restore them after?

Depends whether you have to call an operator which needs another context to be executed properly. Overriding is a good option to avoid changing for e.g. the viewport selection but sometimes you just have to do it so there is nothing like "the best way" (one reason why stackoverflow is so popular), it always depends. Show us your code @Robert and we'll see :)

The code only exists in my head at the moment. I'm trying to map it out before I begin. I'm worried about complex situations where I'm duplicating objects in one function to merge them in another function, each one needing to change the active object and selected objects. And while all of this is going on, the root function driving everything will have to keep its own selection list running that will be sent to the FBX exporter. I should probably make a secondary temporary list for the root function, then select them after everything is finished. Oh well, I think I'm getting close.


text:
Is there a way to auto name my AOV outputs?
So in most other software I use like Houdini and C4D there are tokens you can use to assign auto naming conventions such as the $ (dollar sign) expression.
In C4D $prj will name the output name as the project name. or in Houdini $OS.F will name the output as the "OperatorString.FrameNumber"
Is there anything in Blender that can make outputs a lot easier than manually naming stuff all the time?

You might want to try Loom, added a simple global variable system to the User Prefernces recently as well as a version property based on my answer here. Unfortunately, I hadn't the time to document the features yet but I think all should be quite familiar to you.


text:
Python Timer is not working for me in blender
I need to start animation and stop it in 30 sec
command to stop animation is the same as start, so I'm activating animation before setting delay, and I want it to stop in 30 sec, but its not working for me. Any help would be highly appreciated
from threading import Timer

def  play_animation():
    bpy.ops.screen.animation_play()

play_animation()

t = Timer(30.0, play_animation)
t.start()

https://blender.stackexchange.com/questions/135970/context-is-incorrect-when-calling-from-a-timer

It gives an error:
Traceback (most recent call last):
File "<blender_console>", line 3, in
AttributeError: 'bpy.app' object has no attribute 'timers'

Could it be possible that you are using version 2.7x or prior. Timers were added in 2.80.

I switched to 2.80, but its still not working.
UPD: im not getting this error anymor, but this script isnt doing what I need

Override the context for timer funcs
As discussed here Context is incorrect when calling from a timer the timer is outside the context of the main thread of blender.
To get around this pass the objects to the function when defined, and use these in a context override of any operators.
A quick test reveals that the animation cancell operator requires context members "window" and "screen"
import time, bpy, functools
from bpy import context

def stop(w):
    print("STOP")
    c = {"window" : w,
         "screen" : w.screen
         }
    bpy.ops.screen.animation_cancel(c, restore_frame=False)
    return None

#f = functools.partial(loop, bpy.context.screen.name)

if __name__ == '__main__':
    window = bpy.context.window
    bpy.ops.screen.animation_play()

    bpy.app.timers.register(functools.partial(stop, window), first_interval=30)

The same method could probably be employed with threading.Timer As a rule of thumb, threading and blender don't go together too well. The new timer app was created to alleviate this somewhat.  But since it is still a thread outside blenders main thread it has issues with keeping context.
Please notice the way the index of the window is passed in answer to linked question.  Simply passing the window as shown here could be catastrophic if the window is closed, and hence the reference lost,  between invoking timer and it firing.


text:
Mesh only displays as wireframe?
I'm using non destructive Boolean methods to cut into the mesh. When I duplicate the Boolean it only becomes into a wireframe. I tried deleting the modifier and also tried to convert into mesh from curve trying different options but cant get the solid mesh again.

I'm not sure what you mean, perhaps go in the Properties > Object > Viewport Display > Display As and choose Solid (or Textured)

That's one place it didn't cross my mind! thanks moonboots!

You probably have an addon which sets this to wireframe automatically when you perform a boolean.  Usually, that's helpful, because it lets you see the result!

If the case as mentioned by @Ben please re-edit question with that information.

Maybe something like "Mesh stuck in wireframe after booltools copy"

I'm only using Bool Tool Ad-on: CTRL +  minus on the number pad.

I guess it has to do with the Bool Tool which automatically switch the display of the boolean object you're using to Wire. Go in the Properties panel > Object > Viewport Display > Display As and choose Solid (or Textured)


text:
Specify the inheritance of location, rotation, scale when parenting objects
I have these two objects A and B.
I want A to follow B but only A's location not rotation.
Everytime I use the parenting method, child object always follows every
detail with parent object.
This A object rotates but I want B not to rotate, just follow A's location.
How is it possible? Should I use other method? not parenting one?

Use drivers for that.

To use drivers (properly)  would entail adding three drivers for each x, y and z component of location targeted to same of target object. Any change, eg target would involve editing three drivers. Recommend a constraint as below.

Copy Location Constraint
Blender has a copy location, rotation and scale constraint, as well as a copy transform constraint (ie copy all three_)  Adding all of location, rotation and scale, or copy transform with influence 1 and using world space is the equivalent of parenting.
For question example consider adding just  a copy location constraint on A targeting B

Example default Cube at location of default Camera. With offset unchecked is at exact global location. With it checked will behave similarly to a child, and be offset from parent based on its location
Leaving above the same: If we add another copy location constraint, targeting the Light, with influence 1, the cube will be at location of Light. With influence 0.5 will be half way between Camera and Light.

For fully controllable parenting, you can use the Child Of constraint, which allows you to select which transforms, and which axes of those transforms, the constrained child object inherits from the target parent object.
You can also use the Influence value of the constraint to hand the child from one parent to another.

Drivers are a form of parenting selected properties (location, rotation, scale) with one variable controlling just one property. In your case you add drivers to location.
Drivers also allow more control, with expressions, than simple constraints. See an example


text:
How do I get Collection ID from bpy.data.collections["CollectionNAME"]?
I'm currently creating a script that I'm using to organize a lot of assets at once (I will share it once it works).
I want to use move_to_collection so that I don't have to keep track of all the collections where the asset currently is. But move_to_collection wants a Collection ID, and I only have the collection object retrieved from bpy.data.collections and I would love to get the collection ID from it.

Suggest do not use the operator. It is pretty easy to unlink and re-link the objects: https://blender.stackexchange.com/questions/175146/moving-many-objects-to-a-new-collection/175152#175152 Also to be on the safe side, consider to iterate through the collections in the current scene (bpy.context.scene*) not iterating over data blocks (bpy.data*)

How to move a collection: https://blender.stackexchange.com/questions/172559/python-how-to-move-collection-into-another-collection/172579#172579 (in case)

Are you sure, I will not get an error if I unlink from a collection but the object is not in it?

Not exactly sure what you're talking about... All I can say is that using the index operator Collection["CollectionName"] is even more error prone than anything else. Suggest add more details to your question. Please read: https://blender.stackexchange.com/help/how-to-ask

To reiterate comment 1 above https://devtalk.blender.org/t/where-to-find-collection-index-for-moving-an-object/3289/2?u=batfinger

For any collection which is not Scene Collection:
operator's collection_index matches an index of the collection in the list of View Layer collections.
But there is a +1 shift.
That shift exists because a list of View Layer collections does not include Scene Collection, but collection_index DOES.
*written in Python this looks this way:
import bpy

col_names = bpy.context.view_layer.layer_collection.collection.children.keys()

ind = col_names.index('Collection_Name')

ind+=1

bpy.ops.object.move_to_collection(collection_index=ind)

Erm... I don't get persons who downvote a perfectly correct answer.


text:
How can I delete the same animation/curve channel from all selected objects?
I'm trying to delete some specific channels from many objects. I select them but the dope sheet requires me to expand the Action and Transform menus from each object, then selecting each curve and delete. For example, I'd like to delete specifically the "X Location" channel from all selected objects, but from the UI I could only delete all axes from the location or delete a single channel from only one of the objects.
This is really boring, so I thought I'd use Blender's Python API to automate it. However, I'm very new to it and couldn't find how to show the channel's name to the user.
I'm starting with an operator that would scan all selected items' channels and present a list to the user to select which channel to delete from all selected objects. However, the furthest I got was to list those channels by their data_path and array_index. I have this so far:
for ob in bpy.context.selected_objects:
    anim = ob.animation_data
    for group in anim.action.groups:
        for channel in group.channels:
            print("Channel:", channel)
            print("data_path:", channel.data_path, "   array_index:", channel.array_index)
            print(ob.path_resolve(channel.data_path))

However, the array_index is not really user-readable. So, here are two-questions-in-one:
Can I delete a single channel from all selected objects?
and
How can I present an FCurve's user-readable name to the user, if it is possible without hard-coding?
By the way, I remember that Blender is now translatable, and it seems the path should be in that direction, but I couldn't find it yet.

Find and remove
The fcurves collection of an action has a method to find fcurves from data path and index, and a remove method.
The same action can be linked to multiple objects, so will use a set to find all the actions' fcurves.
There really is no need to look at the group, location x keyframes have data path 'location' and array_index 0.
Test code. Since you mention you are going to convert this to an operator have added the context variable context = bpy.context  Once test code works, lose this and use the context argument passed to operator/panel methods, when pasting into operator code.
import bpy

context = bpy.context

data_path = "location"
index = 0 # location.x or location[0]

#objects = bpy.data.objects # all
#objects = context.scene.objects # all in scene
objects = context.selected_objects # selected

all_fcurves = set(
    o.animation_data.action.fcurves for o in objects
    if o.animation_data and o.animation_data.action
    )

for fcurves in all_fcurves:
    fcurve = fcurves.find(data_path, index=index)
    if fcurve:
        fcurves.remove(fcurve)

for bones the data path is akin to
'pose.bones["Bone"].location`

in which case to find  x location keyframe it could be simpler to replace the find method with
def find(fcurves, data_path, index):
    x = [fc for fc in fcurves
         if fc.data_path.endswith(datapath)
         and fc.array_index == index]
    return x.pop() if x else None

Thanks, I can use your answer later, but you missed the exact point of
my question. I do not know that the user will delete specifically the
X Location channel. Instead, I want to present a list of channels from
all selected objects to the user, so that he will select, for example,
"I want to delete the Z Location from all selected objects". However,
I could not find a way to convert location[2] to "Z Location".

Re-read the question appears to be a pretty good attempt at an answer to part i. Generally the idea is to have one question per question , re part 2
Can get the name of the property via the "RNA" eg if an object has an fcurve with datapath "location" or "rotation_euler"
>>> C.object.bl_rna.properties['location'].name
'Location'

>>> C.object.bl_rna.properties['rotation_euler'].name
'Euler Rotation'

>>> C.object.bl_rna.properties['rotation_euler'].subtype
'EULER'

>>> C.object.bl_rna.properties['location'].subtype
'TRANSLATION'

As for the axis name from index, have asked this question Python RNA getting the names of Vector axes. (eg "g" is color[1])
>>> index = 0
>>> "XYZ"[index]
'X'

and as for your third question, with espanol selected as language.
>>> bpy.app.translations.pgettext("Location")
'Posición'

consult the docs.  https://docs.blender.org/api/current/bpy.app.translations.html#module-bpy.app.translations

Thanks, I can use your answer later, but you missed the exact point of my question. I do not know that the user will delete specifically the X Location channel. Instead, I want to present a list of channels from all selected objects to the user, so that he will select, for example, "I want to delete the Z Location from all selected objects". However, I could not find a way to convert location[2] to "Z Location".

I guess I couldn't get myself understood properly. I treated the two questions as one because I was hoping someone could provide a non-scripting (UI-only) answer that would accomplish what I needed without having to build my own script. But after our initial misunderstanding, your edited answer has everything I need and much more! Even though the answer to your reference question is what I'd consider "hardcoding", that classMap dict is much smaller than I expected and very much acceptable. In fact, this answer is quite informative and will help me a lot. Thank you!


text:
Why I cannot join these two vertices with hotkey J?
I've made the two open vertical lines using the knife tool, but then when I try joining them with the J hotkey, I can't. Does anyone know why this happens? Thank you in advance.

https://ibb.co/4Nmhwhg

How to upload an image to a post

Hi batFINGER, thank you for taking the time to help me. I normally use J to join two vertices in an N-gon, but this time it doesn't work. It turned out there are some duplicated vertices that render the operation failed.

it should work, there must be something in your topology that prevent you from creating the edge, maybe share your file

In edit mode J will make an edge between two vertices, and also cut the underlying faces and edges crossed over by the new connection. This does not work if there is no face associated with a selected vertex.
In your screenshot, the lower vertex looks like it is on the horizontal edge but the lack of selection highlighting shows that it is a floating vertex with only one edge attached to it.
Also looking at the upper selected vertex, you will see that there are two horizontal lines, one orange and one black, this would indicate that you have two horizontal edges, one of which has the selected vertex, there wouldn't appear to be a face attached to these edges.


text:
Can Blender be programmed to visualize cash?
Can Blender can be programmed to illustrate cash for financial investments. For example, one of my investments is worth this today

but that value changes from day to day. Would blender be able to make YouTube videos or not. Thanks for feedback.

Please do not ask closed questions (questions where no/yes would be the answer) Also do not put two different questions in a single question. Also as this seems to be a python question. what have you tried, and where did you get stuck. Also in this specific case where does the data come from.

@J.Bakker Well I would consider a "Can something be done?" to be meant as "How can something be done?" even if it has not much info in it - I consider the 'How' silent, but generally it is true the best is to be explicit to avoid this..:)

Please edit the question and include more details what you are after, so we can better help you how to achieve that. After editing the question may be re-opened.

Hi. Sorry for not getting back for about 24 hours, I just now got an email. What my goal is, is to setup Blender to understand the difference in value from a penny all the way upto a $100 bill. The human mind tends to be better at understanding money for investments or debt on seeing cash instead of just seeing a bank statement. That is my goal. I am not aware of programs that do this. I have been searching on Google without really finding an answer. @J. Bakker thanks for the heads up. I'm just starting out with Blender. I just started watching Blender Guru on YouTube.

The question is whether Python, the programming language used in Blender, can get the data. If Python can get it, either through a text file or from online sources or manual input, then it's perfectly possible to change graphs and swap texts and change more or less anything on the screen according to the data.
import bpy
# changing a text
textName = 'Text' # name of the text object
value = 500.0 # value to be displayed
txt = bpy.data.objects[textName].data.body = str(value) # replacing the text in the text object

# changing the length of an object in order to make a graph
objName = 'Cube' # bar that is supposed to change length
value = 80 # which value does the bar have to represent
bpy.data.objects[objName].scale.z = value / 10 # setting the scale of the bar.

When a bar graph is done like in the script above, it's helpful to put the object origin at the bottom of the bars. That way the scale won't destroy the bottom alignment.

If you want to visualize money with coins and bills, that's possible, too. You can change the position and the visibility of any object:
import bpy

bpy.data.objects['Cube'].location = (1.0, 2.0, 3.0)
bpy.data.objects['Cube'].location.x = 3.0

bpy.data.objects['Cube'].hide = 1
bpy.data.objects['Cube'].hide_render = 1

It's simply a matter of hiding, revealing and arranging.

Hi. please see my reply to Pierre Schiller "Sorry for the confusion. I do not want a graph. If I did, I could use Excel. I want a way to actually show cash. For example, when I asked the question yesterday, my investment was worth $820.12 and today it's crept upto $820.66 I would want the program to understand the difference by being able to show 8 $100 bills, 1 $20 bill 2 quarters (50) cents a dime, a nickel and a penny. That is what I'm looking for. I would guess this has to be rendered. Thanks"

The right place for this detail is in your question.

I think you´d like to do a hub. Otherwise simple animating the scale with reference values on a chart on the side and down would be sufficient. No?
Hub like ->Read data from php/mysql->Write values on a table (text), Blenderaddon.py picks it up and the rest gets represented on Blender. But what puzzles me it's the fact you'd like this to be rendered? Then you´d also need command line...
Like the first answer said: this is too broad subject.

Sorry for the confusion. I do not want a graph. If I did, I could use Excel. I want a way to actually show cash. For example, when I asked the question yesterday, my investment was worth $820.12 and today it's crept upto $820.66 I would want the program to understand the difference by being able to show 8 $100 bills, 1 $20 bill 2 quarters (50) cents a dime, a nickel and a penny. That is what I'm looking for. I would guess this has to be rendered. Thanks

The right place for this detail is in your question.

@Nicholas He's saying you need to add this info to your question by clicking edit and not make it a comment.

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/3.0/


text:
Blender script: add ALL OBJECT to command?
I have got very simple script :
import bpy

bpy.ops.object.select_all(action='SELECT')

bpy.context.object.show_wire = True

bpy.data.objects["Lamp"].show_wire = True

bpy.data.objects["Camera"].show_wire = True

bpy.data.objects["Suzanne.001"].show_wire = True

What i need is that ["Suzanne.001"] will not be specified but rather be something universal for ALL objects in scene, is there something similar like ["all_objects"] or something like that ?

If I understand correctly, you want show_wire to be True for all objects, not just "Suzanne.001"?
If so, all you need to do is iterate over the objects in the scene with a for loop:
for obj in bpy.context.scene.objects:
    obj.show_wire = True

Hope this helps!

Well thank for input, but if I use this let's say in this example :

`import bpy
bpy.ops.object.select_all(action='SELECT')
for obj in bpy.context.scene.objects:
obj.show_wire = True`

It still doesn't show wire on all objects but one. JESUS this text editor is nightmare :D

I'm struggling to repeat your problem, it may help if you upload the blend file you are using.

Also, it's possible that it is showing wire on all objects, but it may seem like it's only showing wire on one object (the selected object). The wire will appear black on unselected objects. Have you checked that all the objects in the scene to see if "Wire" is checked in the display settings?

Also, you don't need bpy.ops.object.select_all(action='SELECT') in your code

Hmm, I will try to add screen to demonstrate my problem. It might be worth noting that I am using Blender 2.8.

I attached screen to OP where you can see that I tried your code but still wire appears only on that one object (on screen i clicked on different object so you can see it is not just graphic thing but wire frame is not ticked there).

This is why it is pointless to ask or answer questions about 2.8. The latest build works fine. Whatever you are using is not today's build. 2.8 is not finished yet. If you want to experiment with it, please do, but right now the way I see it you are just wasting time of the kind people who are trying to help you. That's not a very nice thing to do.

Ok in 2.79 it is indeed working thank you mr. Bollans for solution! Martin Z I am sorry that you see it this way but it really wasn't my intention. I was trying to find it out myself but since i am really newbie in terms of coding I needed help. Yes 2.8 was a problem and I didn't realize that and I will be more careful about that in future, but I don't think I deserve to be accused like that.

Great, glad you got it working!


text:
3d cursor x,y,z does not move with mesh
I have a model that has a root (main) bone added to rear of pelvis. The root bone
is for movement (animation) of model.
 When I'm in pose mode and move model forward using the root bone, I noticed the   x,y,z 3d cursor of the mesh does not move with the mesh.
I have a feeling this will cause problems if I continue to animate. I've decided to stop researching and ask for help. I have posted 3 pictures. The first picture shows model before movement, second picture is after I move Model. The third picture is what it looks like in object mode.
Is this normal? Do I need the 3d cursor xyz  to stay with mesh when I move model in pose mode? If so how.

i've spent forty minutes doing this I apologize about the pictures. The first picture is at the end of my question. The second picture uploaded three times. The third picture did not upload at all. The third picture is not really necessary.  thanks

You can edit your post to correct the pictures. What you call "3d cursor" is the object Origin. If you want to change the position of the whole character, you should do that in Object mode, not Pose mode.

Hi, thank you. The reason I moved it in pose mode is because i'm planning to move the whole character in a animation while moving arms and legs etc. When I move the model for animation, will the object origin still stay in it's original  position? If so, is that normal?

This behaviour is absolutely fine: the bones move vertices only, which have some weight related to their respective vertex group (with the same name). The object (its origin) stays still. If you move the object in object mode you will have weird issues unless you move the rig accordingly.
The usual way to animate is setting both object and rig at the center of the world in object mode, then in pose mode use the root bone to grab your character where he needs to be, and start the animation from there. The root bone can stay still while the rest of the bones are animating the mesh, or can be moved along a path in case of walk cycles or similar.


text:
How do I have two different 'template_icon_view's in a panel?
I want make two template_icon_view previews in  text editor > templates > python > ui_previews_dynamic_enum.py in blender 2.8 or 2.79, but I do not understand how make two different regions of previews.
The original template script is simple, I made my library, but I want two or more library previews inside 1 panel with 2 different directories.
For example:
directory = wm.my_previews_dir

I want another:
directory_two =.....

I just made everything double:
import os
import bpy

def enum_previews_from_directory_items(self, context):
    """EnumProperty callback"""
    enum_items = []

    if context is None:
        return enum_items

    wm = context.window_manager
    directory = wm.my_previews_dir

    # Get the preview collection (defined in register func).
    pcoll = preview_collections["main"]

    if directory == pcoll.my_previews_dir:
        return pcoll.my_previews

    print("Scanning directory: %s" % directory)
    def_dir = os.path.dirname(bpy.data.filepath) + directory[1:]
    if directory and os.path.exists(def_dir):
        # Scan the directory for png files
        image_paths = []
        for fn in os.listdir(def_dir):
            if fn.lower().endswith(".png"):
                image_paths.append(fn)
        for i, name in enumerate(image_paths):
            # generates a thumbnail preview for a file.
            filepath = os.path.join(def_dir, name)
            thumb = pcoll.load(filepath, filepath, 'IMAGE')
            enum_items.append((name, name, "", thumb.icon_id, i))

    pcoll.my_previews = enum_items
    pcoll.my_previews_dir = directory
    return pcoll.my_previews

def enum_previews_from_directory_items2(self, context):
    """EnumProperty callback"""
    enum_items = []

    if context is None:
        return enum_items

    wm = context.window_manager
    directory = wm.my_previews_dir2

    # Get the preview collection (defined in register func).
    pcoll = preview_collections["main2"]

    if directory == pcoll.my_previews_dir2:
        return pcoll.my_previews2

    print("Scanning directory: %s" % directory)
    def_dir = os.path.dirname(bpy.data.filepath) + directory[1:]
    if directory and os.path.exists(def_dir):
        # Scan the directory for png files
        image_paths = []
        for fn in os.listdir(def_dir):
            if fn.lower().endswith(".png"):
                image_paths.append(fn)
        for i, name in enumerate(image_paths):
            # generates a thumbnail preview for a file.
            filepath = os.path.join(def_dir, name)
            thumb = pcoll.load(filepath, filepath, 'IMAGE')
            enum_items.append((name, name, "", thumb.icon_id, i))

    pcoll.my_previews2 = enum_items
    pcoll.my_previews_dir2 = directory
    return pcoll.my_previews2

class PreviewsExamplePanel(bpy.types.Panel):
    """Creates a Panel in the Object properties window"""
    bl_label = "Previews Example Panel"
    bl_idname = "OBJECT_PT_previews"
    bl_space_type = 'PROPERTIES'
    bl_region_type = 'WINDOW'
    bl_context = "object"

    def draw(self, context):
        layout = self.layout
        wm = context.window_manager

        row = layout.row()
        row.prop(wm, "my_previews_dir")

        row = layout.row()
        row.template_icon_view(wm, "my_previews")

        row = layout.row()
        row.prop(wm, "my_previews")

        row = layout.row()
        row.prop(wm, "my_previews_dir2")

        row = layout.row()
        row.template_icon_view(wm, "my_previews2")

        row = layout.row()
        row.prop(wm, "my_previews2")

# We can store multiple preview collections here,
# however in this example we only store "main"
preview_collections = {}

def register():
    from bpy.types import WindowManager
    from bpy.props import (
            StringProperty,
            EnumProperty,
            )

    WindowManager.my_previews_dir = StringProperty(
            name="Folder Path",
            subtype='DIR_PATH',
            default=""
            )

    WindowManager.my_previews = EnumProperty(
            items=enum_previews_from_directory_items,
            )
    WindowManager.my_previews_dir2 = StringProperty(
            name="Folder Path",
            subtype='DIR_PATH',
            default=""
            )

    WindowManager.my_previews2 = EnumProperty(
            items=enum_previews_from_directory_items2,
            )

    # Note that preview collections returned by bpy.utils.previews
    # are regular Python objects - you can use them to store custom data.
    #
    # This is especially useful here, since:
    # - It avoids us regenerating the whole enum over and over.
    # - It can store enum_items' strings
    #   (remember you have to keep those strings somewhere in py,
    #   else they get freed and Blender references invalid memory!).
    import bpy.utils.previews
    pcoll = bpy.utils.previews.new()
    pcoll.my_previews_dir = ""
    pcoll.my_previews = ()
    pcoll2 = bpy.utils.previews.new()
    pcoll2.my_previews_dir2 = ""
    pcoll2.my_previews2 = ()

    preview_collections["main"] = pcoll
    preview_collections["main2"] = pcoll2

    bpy.utils.register_class(PreviewsExamplePanel)

def unregister():
    from bpy.types import WindowManager

    del WindowManager.my_previews

    for pcoll in preview_collections.values():
        bpy.utils.previews.remove(pcoll)
    preview_collections.clear()

    bpy.utils.unregister_class(PreviewsExamplePanel)

if __name__ == "__main__":
    register()

I am sure It can be done more professionally, but it's good starting point.
If You want more than two You should reed about collections

Nice i try it and work. Nice trick

Seems to have problems because it does not load any image, not even if I put a specific directory in C:  do you give this problem to you too?

I am working on Linux and I had the same problem. I solved id by adding print(def_dir) almost everywhere, and print(os.path.exists(def_dir)) - has to be true. Just  edit code until def_dir will be correct. And make sure Your images are .png.


text:
Ho to emulate Grab/Move (G) with python script?
After a few hours of searching, I have not found documentation on how to emulate the pressure of the "G" key that allows you to move an object freely with the mouse. I have a modal function and I would like to insert this command to select an object and keep it on the mouse.
the command on blender suggests bpy.ops.transform.translate()
but I can not find options for this.

This question was asked previously and don't have an answer, may be there's no way to do that, but don't delete your question, may be now it would have a answer.

I think is possible. Addon "Snap utilities" have inside a function "Move" and that function similar to what I'm looking for  :)

If you have fixed that, post your answer so others can see it..

I've found this question searching solution for same one. I use this line : bpy.ops.transform.translate('INVOKE_DEFAULT'). It  emulates the "G" key for me.


text:
Blender Python: Generate custom property (due to error bpy_struct[key]: key "PropertyName" not found)?
Is there a way to force Blender to generate a custom property ahead of time? It looks like custom properties added to objects are only generated when the user changes them from the default in the UI, which makes sense. But I've defined a setter handler in a custom property that spreads it to other objects (object_b.custom_prop = object_a.custom_prop), and Blender halts execution of that setter when it encounters an object that hasn't had its property "generated" yet.
Edit: After discovering the console output messages, Blender throws the error "KeyError: 'bpy_struct[key]: key "PropertyName" not found' when it encounters one of these objects before I manually prime it by manipulating the UI control for it. Still have not found an answer to this.
So I'm wondering if there is something I can do in this situation that will force the property to be generated? This is essentially the code in my setter that spreads it to other objects:
for obj in selected_list:
   value = obj["custom_prop"]
   value = math( value, active_object["custom_prop"] )
   obj["custom_prop"] = value

It works fine as long as I "prime" the involved objects by manipulating their property first. But otherwise, it just stops when it encounters one that hasn't been primed.

When a custom property is accessed as obj["custom_prop"], it will throw an error in the console ('bpy_struct[key]: key "PropertyName" not found') if that property has not been assigned yet. To fix this, you can instead use obj.get("custom_prop", DEFAULT_VALUE). This will not throw an error, and will return the default value if the property doesn't yet exist.
I'm assuming we should ALWAYS use the syntax obj.get("custom_prop", DEFAULT_VALUE) instead of obj["custom_prop"]? Can anyone confirm this? Or at least in situations where we may be reading the value before writing to it.
I'm very new at this, so anyone feel free to chime in here.