# io_import_minecraft # ##### BEGIN GPL LICENSE BLOCK ##### # # 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 2 # 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, write to the Free Software Foundation, # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # # ##### END GPL LICENSE BLOCK ##### # # bl_info = { # "name": "Import: Minecraft b1.7+", # "description": "Importer for viewing Minecraft worlds", # "author": "Adam Crossan (acro)", # "version": (1,6,3), # "blender": (2, 6, 0), # "api": 41226, # "location": "File > Import > Minecraft", # "warning": '', # used for warning icon and text in addons panel # "wiki_url": "http://randomsamples.info/project/mineblend", # "category": "Import-Export"} DEBUG_SCENE=False # To support reload properly, try to access a package var, if it's there, reload everything #if "bpy" in locals(): # import imp # if "mineregion" in locals(): # imp.reload(mineregion) #import bpy #from bpy.props import StringProperty, FloatProperty, IntProperty, BoolProperty, EnumProperty import imp import mineregion #def setSceneProps(scn): # #Set up scene-level properties # bpy.types.Scene.MCLoadNether = BoolProperty( # name = "Load Nether", # description = "Load Nether (if present) instead of Overworld.", # default = False) # scn['MCLoadNether'] = False # return #setSceneProps(bpy.context.scene) # def createTestScene(): # bpy.ops.scene.new(type='NEW') # bpy.context.scene.render.engine = 'CYCLES' # # plane # bpy.ops.mesh.primitive_plane_add(radius=1, view_align=True, enter_editmode=False, location=(0,0,0), rotation=(0,0,0), layers = (True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False)) # bpy.ops.transform.resize(value=(10,10,10), constraint_axis=(False, False, False), constraint_orientation='GLOBAL', mirror=False, proportional='DISABLED', proportional_edit_falloff='SMOOTH', proportional_size=1) # bpy.ops.material.new() # # cube # bpy.ops.mesh.primitive_cube_add(radius=1, view_align=True, enter_editmode=False, location=(0,0,0), rotation=(0,0,0), layers = (True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False)) # # FIXME - error # #bpy.context.space_data.context='MATERIAL' # bpy.ops.transform.translate(value=(0.55,0.17,1.14), constraint_axis=(False,False, False), constraint_orientation='GLOBAL', mirror=False, proportional='DISABLED', proportional_edit_falloff='SMOOTH', proportional_size=1) # # set material to leaves? # bpy.ops.object.editmode_toggle() # bpy.ops.uv.unwrap(method='CONFORMAL', margin=0.001) # # uv mapping - how do we tell blender? # #bpy.ops.transform.resize(value=(0.0368432,0.0368432,0.0368432), constraint_axis=(False,False,False), constraint_orientation='GLOBAL', mirror=False, proportional='DISABLED', proportional_edit_falloff='SMOOTH', proportional_size=1) # #bpy.ops.transform.translate(value=(-0.202301, 0.07906, 0), constraint_axis=(False,False,False), constraint_orientation='GLOBAL', mirror=False, proportional_falloff='SMOOTH', proportional_size=1) # bpy.ops.object.editmode_toggle() # # lights... # bpy.ops.object.lamp_add(type='SUN', view_align=True, location=(-8.12878,5.39259,9.70453), rotation=(-0.383973,0,0), layers=(True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False)) # # camera... # bpy.ops.object.camera_add(view_align=True, enter_editmode=False, location=(-8.12878,-9.13302,7.87796), rotation=(0,0,0), layers=(True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False)) # #bpy.context.space_data.context='CONSTRAINT' # bpy.ops.object.constraint_add(type='TRACK_TO') # bpy.context.object.constraints["Track To"].target = bpy.data.objects["Cube.001"] # bpy.context.object.constraints["Track To"].track_axis = 'TRACK_NEGATIVE_Z' # bpy.context.object.constraints["Track To"].up_axis = 'UP_Y' #Menu 'button' for the import menu (which calls the world selector)... # class MinecraftWorldSelector(bpy.types.Operator): #"""An operator defining a dialogue for choosing one on-disk Minecraft world to load. #This supplants the need to call the file selector, since """Minecraft worlds require a preset specific folder structure of multiple files which cannot be selected singly.""" bl_idname = "mcraft.selectworld" bl_label = "Select Minecraft World" #bl_space_type = "PROPERTIES" #Possible placements for these: bl_region_type = "WINDOW" #TODO: Make this much more intuitive for the user! #Would be better if could define min[x,y,z] and max[x,y,z] and load between these point mcLoadAtCursor = False #Loads as if 3D cursor offset in viewport was the player (load) position. mcLowLimit = 60 #The lowest depth layer to load. (High=256, Sea=64, Low=0) mcHighLimit = 128 #The highest layer to load. (High=256, Sea=64, Low=0) mcLoadRadius = 5 # 'Load Radius - The half-width of the load range around load-pos. # e.g, 4 will load 9x9 chunks around the load centre # WARNING! Above 10, this gets slow and eats LOTS of memory! mcOmitStone = False # When True, do not import common blocks such as stone & dirt blocks (overworld) or netherrack (nether). mcDimenSelectList = '0' #Which dimension should be loaded? - 0=Overworld; 1=Nether, 2=The End mcShowSlimeSpawns = False #'Display green markers showing slime-spawn locations mcUseCyclesMats = False #Blender Setting: Set up default materials for use with Cycles Render Engine instead of Blender Internal mcFasterViewport = False #Blender Setting: Disable display of common blocks (stone, dirt, etc.) in the viewport for better performance. mcSurfaceOnly = False #Omit underground blocks. Significantly better viewing and rendering performance. mcOmitMobs = True # When True, do not load mobs (creepers, skeletons, zombies, etc.) in world #may need to define loadnether and loadend as operators...? # omit Dirt toggle option. # height-limit option (only load down to a specific height) -- could be semi-dynamic and delve deeper when air value for the # column in question turns out to be lower than the loading threshold anyway. #surfaceOnly ==> only load surface, discard underground areas. Doesn't count for nether. # Load Nether is, obviously, only available if selected world has nether) # Load End. Who has The End?! Not I! #When specifying a property of type EnumProperty, ensure you call the constructing method correctly. #Note that items is a set of (identifier, value, description) triples, and default is a string unless you switch on options=ENUM_FLAG in which case make default a set of 1 string. #Need a better way to handle this variable: (possibly set it as a screen property) # import mineregion wlist = mineregion.getWorldSelectList() if wlist is not None: revwlist = wlist[::-1] mcWorldSelectList = 0 #Which Minecraft save should be loaded? else: mcWorldSelectList = 0 #Which Minecraft save should be loaded? #TODO: on select, check presence of DIM-1 etc. print("List of Worlds: wlist:: ", wlist) netherWorlds = [w[0] for w in wlist if mineregion.hasNether(w[0])] print("List of worlds with Nether: ", netherWorlds) endWorlds = [e[0] for e in wlist if mineregion.hasEnd(e[0])] print("List of worlds with The End: ", endWorlds) #my_worldlist = bpy.props.EnumProperty(items=[('0', "A", "The A'th item"), ('1', 'B', "Bth item"), ('2', 'C', "Cth item"), ('3', 'D', "dth item"), ('4', 'E', 'Eth item')][::-1], default='2', name="World", description="Which Minecraft save should be loaded?") # def execute(self, context): #self.report({"INFO"}, "Loading world: " + str(self.mcWorldSelectList)) #thread.sleep(30) #self.report({"WARNING"}, "Foo!") #from . import mineregion # scn = context.scene mcLoadDimenNether = True if mcDimenSelectList=='1' else False mcLoadDimenEnd = True if mcDimenSelectList=='2' else False # FIXME - when omitmobs is false, mobs will sometimes still not be imported (related to reload issue?) opts = {"omitstone": mcOmitStone, "showslimes": mcShowSlimeSpawns, "atcursor": mcLoadAtCursor, "highlimit": mcHighLimit, "lowlimit": mcLowLimit, "loadnether": mcLoadDimenNether, "loadend": mcLoadDimenEnd, "usecycles": mcUseCyclesMats, "omitmobs": mcOmitMobs, "fasterViewport": mcFasterViewport, "surfaceOnly": mcSurfaceOnly} #print(str(opts)) #get selected world name instead via bpy.ops.mcraft.worldselected -- the enumeration as a property/operator...? mineregion.readMinecraftWorld(str(mcWorldSelectList), mcLoadRadius, opts) # for s in bpy.context.area.spaces: # iterate all space in the active area # if s.type == "VIEW_3D": # check if space is a 3d-view # space = s # space.clip_end = 10000.0 #run minecraftLoadChunks #if DEBUG_SCENE: # createTestScene() # return {'FINISHED'} # def invoke(self, context, event): # context.window_manager.invoke_props_dialog(self, width=350,height=250) # return {'RUNNING_MODAL'} # # # def draw(self, context): # layout = self.layout # col = layout.column() # col.label(text="Choose import options") # # row = col.row() # row.prop(self, "mcLoadAtCursor") # # row = col.row() # # sub = col.split(percentage=0.5) # colL = sub.column(align=True) # colL.prop(self, "mcShowSlimeSpawns") # # cycles = None # if hasattr(bpy.context.scene, 'cycles'): # cycles = bpy.context.scene.cycles # row2 = col.row() # if cycles is not None: # row2.active = (cycles is not None) # row2.prop(self, "mcUseCyclesMats") # # row3 = col.row() # row3.prop(self, "mcOmitStone") # row3.prop(self, "mcOmitMobs") # # row = col.row() # row.prop(self,"mcFasterViewport") # #row.prop(self,"mcSurfaceOnly") # # #if cycles: # #like this from properties_data_mesh.py: # ##layout = self.layout # ##mesh = context.mesh # ##split = layout.split() # ##col = split.column() # ##col.prop(mesh, "use_auto_smooth") # ##sub = col.column() # ##sub.active = mesh.use_auto_smooth # ##sub.prop(mesh, "auto_smooth_angle", text="Angle") # #row.operator( # #row.prop(self, "mcLoadEnd") #detect folder first (per world...) # # #label: "loading limits" # row = layout.row() # row.prop(self, "mcLowLimit") # row = layout.row() # row.prop(self, "mcHighLimit") # row = layout.row() # row.prop(self, "mcLoadRadius") # # row = layout.row() # row.prop(self, "mcDimenSelectList") # #col = layout.column() # # row = layout.row() # row.prop(self, "mcWorldSelectList") # #row.operator("mcraft.worldlist", icon='') # col = layout.column() # def worldchange(self, context): # ##UPDATE (ie read then write back the value of) the property in the panel # #that needs to be updated. ensure it's in the scene so we can get it... # #bpy.ops.mcraft.selectworld('INVOKE_DEFAULT') # #if the new world selected has nether, then update the nether field... # #in fact, maybe do that even if it doesn't. # #context.scene['MCLoadNether'] = True # return {'FINISHED'} # # class MineMenuItemOperator(bpy.types.Operator): # bl_idname = "mcraft.launchselector" # bl_label = "Needs label but label not used" # # def execute(self, context): # bpy.ops.mcraft.selectworld('INVOKE_DEFAULT') # return {'FINISHED'} # # bpy.utils.register_class(MinecraftWorldSelector) # bpy.utils.register_class(MineMenuItemOperator) #bpy.utils.register_class(MCraft_PT_worldlist) #Forumsearch tip!! FINDME: #Another way would be to update a property that is displayed in your panel via layout.prop(). AFAIK these are watched and cause a redraw on update. # # def mcraft_filemenu_func(self, context): # self.layout.operator("mcraft.launchselector", text="Minecraft (.region)", icon='MESH_CUBE') # # # def register(): # #bpy.utils.register_module(__name__) # bpy.types.INFO_MT_file_import.append(mcraft_filemenu_func) # adds the operator action func to the filemenu # # def unregister(): # #bpy.utils.unregister_module(__name__) # bpy.types.INFO_MT_file_import.remove(mcraft_filemenu_func) # removes the operator action func from the filemenu # # if __name__ == "__main__": # register()