mc2mt/__init__.py

288 lines
13 KiB
Python

# 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 #####
# <pep8 compliant>
# 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
# this would mean an edit in mineregion.py approx line 844: for z in range(pZ-loadRadius, pZ+loadRadius):
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 = 100 # '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 = wlist[0][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(mcWorldSelectList))
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()