0
$\begingroup$

Ok. So, I'm very new to Python, and I'm not very skilled with Blender either. I do have some C# experience, if it helps.

I'm working on a module/add-on that takes OBJs made with World Machine and puts them in place in the Blender scene. I was trying to work with heightmaps, but seams never matched up. I've done some manual pulling around, and I know these can line up perfectly.


My problem is two fold:

A) The filename for each OBJ describes the location. They all have the naming format of "object_x000_y000.obj" Basically, where the numbers are, are how many units to the left or up I want to move the obj. But extracting this information from the file name makes NO Sense to me in python. I struggled with this in C#, but I can do it after some work. But python is like Greek to me right now. Any Documentation to help me chew up strings would be nice.

B) I'm struggling with understanding how to affect each individual object gets imported anyway. I want to rename and move each object. I wouldn't mind learning how to change the size for future reference also. I'm trying to avoid using an array, instead I want to work each import at a time per iteration in the loop. I would do this in C# by making a method I would loop, and return the "finished" object, but I don't get how to do this in Python.

Below is the entire script for reference, including comments that describe my problem:

import bpy
import os

from bpy.props import(StringProperty,
                     PointerProperty,
                     )

from bpy.types import(Panel,
                     Operator,
                     AddonPreferences,
                     PropertyGroup,
                     )

class MySettings(PropertyGroup):

    path = StringProperty(
    name="",
    description ="Path to Directory",
    default ="",
    maxlen=1024,
    subtype='DIR_PATH')


class WMImporterPanel(Panel):
    bl_idname = "OBJECT_PT_WMImporter"
    bl_category = "WorldMachine Importer"
    bl_label = "WM Importer"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'TOOLS'
    bl_context = 'objectmode'


    def draw(self, context):
        layout = self.layout
        col = layout.column(align=True)
        scn = context.scene


        #Selecting Directory/Folder path
        col.label(text="Directory of Files")
        col.separator()
        dirpath = col.prop(scn.my_tool, "path", text="")


        #Button to perform import of meshes
        col.separator()
        col.operator("wmimport.importmeshes", text = "Import Meshes")

class OBJECT_OT_ImportButton(Operator):
    bl_idname = "wmimport.importmeshes"
    bl_label ="Import Meshes"

    def execute(self,context):
        scn = context.scene
        dirpath = scn.my_tool.path

        #print(dirpath)

        file_list = os.listdir(dirpath)

        obj_list = [item for item in file_list if item[-3:] == 'obj']
        #for file in obj_list:
        #    print (file)


        # Detect Naming Convention
        # Need Help
        # I want to pull the first file and rip the format from it.
        # Files come in the format of <filename>_x000_y000.obj
        # I want to use the filename to name each object imported, so if I called it Island
        # the object in blender will be called something like Island(X,Y)
        # where X = number following x in filename, and Y likewise.

        for item in obj_list:

            #Detect Location
            # Need Help
            #I want to get the X and Y value in the filename, so I can use that to
            #increment the object in corrosponding directions.


            fullpath = os.path.join(dirpath,item)
            bpy.ops.import_scene.obj(filepath=fullpath, axis_forward='Y', axis_up='Z')
            # Should I assign this obj to a variable?
            # newObj = bpy.ops.import_scene.obj(filepath=fullpath, axis_forward='Y', axis_up='Z')

        return{'FINISHED'}

def register():
    bpy.utils.register_module(__name__)
    bpy.types.Scene.my_tool = PointerProperty(type=MySettings)

def unregister():
    bpy.utils.unregister_module(__name__)
    del bpy.types.Scene.my_tool

if __name__ == "__main__":
    register()
$\endgroup$
  • $\begingroup$ For more pythonic questions (like your part 1) stackoverflow is a great resource. stackoverflow.com/questions/2175080/sscanf-in-python $\endgroup$ – batFINGER Jan 16 '17 at 16:09
  • 1
    $\begingroup$ The possibilities are endless. I'd go with a regex to find all digits in the filename in combination with a list comprehension in order to convert all strings into floats, this should be save enough in this case. Here is an example based on this answer. $\endgroup$ – p2or Jan 16 '17 at 16:49
1
$\begingroup$

For problem A, you can use splitting and slicing in Python:

def get_nameXY(item):
    name_set = item.split('_') #splits the string at every '_', returns a list
    x = name_set[1][1:] #gets the second value in the list starting at the second character
    y = name_set[2][1:-4] #gets the third value in the list starting at the second character and omitting the last four characters
    name = name_set[0] + '(' + x + ',' + y + ')' #combine the first value with x and y
    return name, float(x), float(y) #return the name with x and y as floats

Then you can call that function in you loop to name and position your imported object.(problem B)

for item in obj_list:

    #Detect Location
    name, x, y = get_nameXY(item)
    for obj in bpy.data.objects:
        obj.select = False #deselect all objects so imported object will be the only one selected

    fullpath = os.path.join(dirpath,item)
    bpy.ops.import_scene.obj(filepath=fullpath, axis_forward='Y', axis_up='Z')

    new_obj = bpy.context.selected_objects[0] # get object from list of selected
    new_obj.name = name #set the new name
    new_obj.location = (x,y,0)#set the location

I wasn't sure if your x,y was an actual position, but you can see how to get it and use it.

| improve this answer | |
$\endgroup$
  • $\begingroup$ I was having some trouble with split before. I did some heavy research before you answered, so I kinda expected that to be the key. Thing is, for like 45 mins, I didn't know that there was 2 underscores before the xValue, so I was getting an empty... But I also really appreciate the example, cause I can see how it relates to how I would make a method in C#. I'm gonna hit the forms about 'def' $\endgroup$ – Alexander Meyers Jan 16 '17 at 16:23
  • $\begingroup$ Just got it plugged into the script. I had to multiply X and Y by 2, but otherwise it WORKS PERFECTLY. Thank you so much for your help. You didn't just solve my problem, but helped me understand Python better $\endgroup$ – Alexander Meyers Jan 16 '17 at 16:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.