Skip to content
Snippets Groups Projects
io_import_gimp_image_to_scene.py 19.2 KiB
Newer Older
  • Learn to ignore specific revisions
  • # ##### 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_addon_info = {
    
    	"name": "Import GIMP Image to Scene (.xcf, .xjt)",
    
    	"author": "Daniel Salazar (ZanQdo)",
    	"version": (2,0,0),
    	"blender": (2, 5, 5),
    	"api": 33419,
    	"location": "File > Import > GIMP Image to Scene(.xcf, .xjt)",
    	"description": "Imports GIMP multilayer image files into 3D Layers",
    	"warning": "XCF import requires xcftools installed",
    	"wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"\
    		"Scripts/File_I-O/GIMPImageToScene",
    	"tracker_url": "http://projects.blender.org/tracker/index.php?"\
    		"func=detail&aid=25136&group_id=153&atid=469",
    	"category": "Import/Export"}
    
    """
    This script imports GIMP layered image files into 3D Scenes (.xcf, .xjt)
    """
    
    def main(File, Path, LayerViewers, MixerViewers, LayerOffset,\
    	LayerScale, OpacityMode, PremulAlpha, ShadelessMats,\
    	SetCamera, SetupCompo, GroupUntagged, Ext):
    	
    	#-------------------------------------------------
    	
    	#Folder = '['+File.rstrip(Ext)+']'+'_images/'
    	Folder = 'images_'+'['+File.rstrip(Ext)+']/'
    	
    	if bpy.data.is_dirty:
    		PathSaveRaw = Path+Folder
    		PathSave = PathSaveRaw.replace(' ', '\ ')
    		try: os.mkdir(PathSaveRaw)
    		except: pass
    	else:
    		PathSave = bpy.data.filepath
    		RSlash = PathSave.rfind('/')
    		PathSaveRaw = PathSave[:RSlash+1]+Folder
    		PathSave = PathSaveRaw.replace(' ', '\ ')
    		try: os.mkdir(PathSaveRaw)
    		except: pass
    		PathSaveRaw = bpy.path.relpath(PathSaveRaw)+'/'
    	
    	PathRaw = Path
    	Path = Path.replace(' ', '\ ')
    	if Ext == '.xjt':
    		ExtSave = '.jpg'
    		#-------------------------------------------------
    		# EXTRACT XJT
    		import tarfile
    		
    		IMG = tarfile.open ('%s%s' % (PathRaw, File))
    		PRP = IMG.extractfile('PRP')
    		
    		Members = IMG.getmembers()
    		
    		for Member in Members:
    			Name = Member.name
    			if Name.startswith('l') and Name.endswith('.jpg'):
    				IMG.extract(Name, path=PathSaveRaw)
    		
    		#-------------------------------------------------
    		# INFO XJT
    		IMGs = []
    		for Line in PRP.readlines():
    			Line = str(Line)
    			
    			if Line.startswith("b'GIMP_XJ_IMAGE"):
    				for Segment in Line.split():
    					if Segment.startswith('w/h:'):
    						ResX, ResY = map (int, Segment[4:].split(','))
    			if Line.startswith("b'L") or Line.startswith("b'l"):
    				
    				if Line.startswith("b'L"): HasAlpha = True
    				else: HasAlpha = False
    				
    				md = None
    				op = 1
    				ox, oy = 0,0
    				
    				for Segment in Line.split():
    					
    					if Segment.startswith("b'"):
    						imageFile = 'l' + Segment[3:] + '.jpg'
    						imageFileAlpha ='la'+Segment[3:]+'.jpg'
    						
    						# Get Widht and Height from images
    						data = open(PathSaveRaw+imageFile, "rb").read()
    						
    						hexList = []
    						for ch in data:
    							byt = "%02X" % ch
    							hexList.append(byt)
    						
    						for k in range(len(hexList)-1):
    							if hexList[k] == 'FF' and (hexList[k+1] == 'C0' or hexList[k+1] == 'C2'):
    								ow = int(hexList[k+7],16)*256 + int(hexList[k+8],16)
    								oh = int(hexList[k+5],16)*256 + int(hexList[k+6],16)
    					
    					elif Segment.startswith('md:'): # mode
    						md = Segment[3:]
    						
    					elif Segment.startswith('op:'): # opacity
    						op = float(Segment[3:])*.01
    					
    					elif Segment.startswith('o:'): # origin
    						ox, oy = map(int, Segment[2:].split(','))
    					
    					elif Segment.startswith('n:'): # name
    						n = Segment[3:-4]
    						OpenBracket = n.find ('[')
    						CloseBracket = n.find (']')
    						
    						if OpenBracket != -1 and CloseBracket != -1:
    							RenderLayer = n[OpenBracket+1:CloseBracket]
    							NameShort = n[:OpenBracket]
    							
    						else:
    							RenderLayer = n
    							NameShort = n
    						
    						os.rename(PathSaveRaw+imageFile, PathSaveRaw+NameShort+'.jpg')
    						if HasAlpha: os.rename(PathSaveRaw+imageFileAlpha, PathSaveRaw+NameShort+'_A'+'.jpg')
    						
    				IMGs.append({'LayerMode':md, 'LayerOpacity':op,\
    							'LayerName':n, 'LayerNameShort':NameShort,\
    							'RenderLayer':RenderLayer, 'LayerCoords':[ow, oh, ox, oy], 'HasAlpha':HasAlpha})
    	
    	else: # Ext == '.xcf':
    		ExtSave = '.png'
    		#-------------------------------------------------
    		# CONFIG
    		XCFInfo = 'xcfinfo'
    		XCF2PNG = 'xcf2png'
    		#-------------------------------------------------
    		# INFO XCF
    		
    		CMD = '%s %s%s' % (XCFInfo, Path, File)
    		
    		Info = os.popen(CMD)
    		
    		IMGs = []
    		for Line in Info.readlines():
    			if Line.startswith ('+'):
    				
    				Line = Line.split(' ', 4)
    				
    				RenderLayer = Line[4]
    				
    				OpenBracket = RenderLayer.find ('[')
    				CloseBracket = RenderLayer.find (']')
    				
    				if OpenBracket != -1 and CloseBracket != -1:
    					RenderLayer = RenderLayer[OpenBracket+1:CloseBracket]
    					NameShort = Line[4][:OpenBracket]
    				else:
    					NameShort = Line[4].rstrip()
    					if GroupUntagged:
    						RenderLayer = '__Undefined__'
    					else:
    						RenderLayer = NameShort
    				
    				LineThree = Line[3]
    				Slash = LineThree.find('/')
    				if Slash == -1:
    					Mode = LineThree
    					Opacity = 1
    				else:
    					Mode = LineThree[:Slash]
    					Opacity = float(LineThree[Slash+1:LineThree.find('%')])*.01
    				
    				IMGs.append ({\
    					'LayerMode':Mode,\
    					'LayerOpacity':Opacity,\
    					'LayerName':Line[4].rstrip(),\
    					'LayerNameShort':NameShort,\
    					'LayerCoords':list(map(int, Line[1].replace('x', ' ').replace('+', ' +').replace('-', ' -').split())),\
    					'RenderLayer':RenderLayer,\
    					'HasAlpha':True,\
    					})
    			elif Line.startswith('Version'):
    				ResX, ResY = map (int, Line.split()[2].split('x'))
    		
    		#-------------------------------------------------
    		# EXTRACT XCF
    		if OpacityMode == 'BAKE':
    			Opacity = ''
    		else:
    			Opacity = ' --percent 100'
    		for Layer in IMGs:
    			CMD = '%s -C %s%s -o %s%s.png "%s"%s' %\
    			(XCF2PNG, Path, File, PathSave, Layer['LayerName'].replace(' ', '_'), Layer['LayerName'], Opacity)
    			os.system(CMD)
    	
    	#-------------------------------------------------
    	Scene = bpy.context.scene
    	#-------------------------------------------------
    	# CAMERA
    	
    	if SetCamera:
    		bpy.ops.object.camera_add(location=(0, 0, 10))
    		
    		Camera = bpy.context.active_object.data
    		
    		Camera.type = 'ORTHO'
    		Camera.ortho_scale = ResX * .01
    	
    	#-------------------------------------------------
    	# RENDER SETTINGS
    	
    	Render = Scene.render
    	
    	if SetCamera:
    		Render.resolution_x = ResX
    		Render.resolution_y = ResY
    		Render.resolution_percentage = 100
    	if PremulAlpha: Render.alpha_mode = 'PREMUL'
    	
    	#-------------------------------------------------
    	# 3D VIEW SETTINGS
    	
    	Scene.game_settings.material_mode = 'GLSL'
    	
    	Areas = bpy.context.screen.areas
    	
    	for Area in Areas:
    		if Area.type == 'VIEW_3D':
    			Area.active_space.viewport_shade = 'TEXTURED'
    			Area.active_space.show_textured_solid = True
    			Area.active_space.show_floor = False
    	
    	#-------------------------------------------------
    	# 3D LAYERS
    	
    	def Make3DLayer (Name, NameShort, Z, Coords, RenderLayer, LayerMode, LayerOpacity, HasAlpha):
    		
    		# RenderLayer
    		
    		if SetupCompo:
    			if not bpy.context.scene.render.layers.get(RenderLayer):
    				
    				bpy.ops.scene.render_layer_add()
    				
    				LayerActive = bpy.context.scene.render.layers.active
    				LayerActive.name = RenderLayer
    				LayerActive.use_pass_vector = True
    				LayerActive.use_sky = False
    				LayerActive.use_edge_enhance = False
    				LayerActive.use_strand = False
    				LayerActive.use_halo = False
    				
    				global LayerNum
    				for i in range (0,20):
    					if not i == LayerNum:
    						LayerActive.layers[i] = False
    				
    				bpy.context.scene.layers[LayerNum] = True
    				
    				LayerFlags[RenderLayer] = bpy.context.scene.render.layers.active.layers
    				
    				LayerList.append([RenderLayer, LayerMode, LayerOpacity])
    				
    				LayerNum += 1
    		
    		# Object
    		bpy.ops.mesh.primitive_plane_add(\
    		view_align=False,\
    		enter_editmode=False,\
    		rotation=(0, 0, pi))
    		
    		bpy.ops.object.rotation_apply()
    		
    		Active = bpy.context.active_object
    		
    		if SetupCompo:
    			Active.layers = LayerFlags[RenderLayer]
    		
    		Active.location = (\
    			(float(Coords[2])-(ResX*0.5))*LayerScale,\
    			(-float(Coords[3])+(ResY*0.5))*LayerScale, Z)
    		
    		for Vert in Active.data.vertices:
    			Vert.co[0] += 1
    			Vert.co[1] += -1
    			
    		Active.dimensions = float(Coords[0])*LayerScale, float(Coords[1])*LayerScale, 0
    		
    		bpy.ops.object.scale_apply()
    		
    		bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY', center='MEDIAN')
    		
    		Active.show_wire = True
    		
    		Active.name = NameShort
    		bpy.ops.mesh.uv_texture_add()
    		
    		# Material
    		
    		'''if bpy.data.materials.get(NameShort):
    			Mat = bpy.data.materials[NameShort]
    			if not Active.material_slots:
    				bpy.ops.object.material_slot_add()
    			Active.material_slots[0].material = Mat
    		else:'''
    		
    		Mat = bpy.data.materials.new(NameShort)
    		Mat.diffuse_color = (1,1,1)
    		Mat.use_raytrace = False
    		Mat.use_shadows = False
    		Mat.use_cast_buffer_shadows = False
    		Mat.use_cast_approximate = False
    		if HasAlpha:
    			Mat.use_transparency = True
    			if OpacityMode == 'MAT': Mat.alpha = LayerOpacity
    			else: Mat.alpha = 0
    		if ShadelessMats: Mat.use_shadeless = True
    		
    		if Ext == '.xcf':
    			# Color & Alpha PNG
    			Tex = bpy.data.textures.new(NameShort, 'IMAGE')
    			Tex.extension = 'CLIP'
    			Tex.use_preview_alpha = True
    			
    			Img = bpy.data.images.new(NameShort)
    			Img.source = 'FILE'
    			if PremulAlpha: Img.use_premultiply = True
    			Img.filepath = '%s%s%s' % (PathSaveRaw, Name, ExtSave)
    			
    
    			UVFace = Active.data.uv_textures[0].data[0]
    			UVFace.image = Img
    			UVFace.use_image = True
    			
    
    			Tex.image = Img
    			
    			Mat.texture_slots.add()
    			TexSlot = Mat.texture_slots[0]
    			TexSlot.texture = Tex
    			TexSlot.use_map_alpha = True
    			TexSlot.texture_coords = 'UV'
    			if OpacityMode == 'TEX': TexSlot.alpha_factor = LayerOpacity
    			elif OpacityMode == 'MAT': TexSlot.blend_type = 'MULTIPLY'
    		
    		else: # Ext == '.xjt'
    			# Color JPG
    			Tex = bpy.data.textures.new(NameShort, 'IMAGE')
    			Tex.extension = 'CLIP'
    			
    			Img = bpy.data.images.new(NameShort)
    			Img.source = 'FILE'
    			Img.filepath = '%s%s%s' % (PathSaveRaw, Name, ExtSave)
    			
    
    			UVFace = Active.data.uv_textures[0].data[0]
    			UVFace.image = Img
    			UVFace.use_image = True
    			
    
    			Tex.image = Img
    			
    			Mat.texture_slots.add()
    			TexSlot = Mat.texture_slots[0]
    			TexSlot.texture = Tex
    			TexSlot.texture_coords = 'UV'
    			
    			if HasAlpha:
    				# Alpha JPG
    				Tex = bpy.data.textures.new(NameShort+'_A', 'IMAGE')
    				Tex.extension = 'CLIP'
    				Tex.use_preview_alpha = True
    				Tex.use_alpha = False
    				
    				Img = bpy.data.images.new(NameShort+'_A')
    				Img.source = 'FILE'
    				if PremulAlpha: Img.use_premultiply = True
    				Img.filepath = '%s%s_A%s' % (PathSaveRaw, Name, ExtSave)
    				
    				Tex.image = Img
    				
    				Mat.texture_slots.add()
    				TexSlot = Mat.texture_slots[1]
    				TexSlot.texture = Tex
    				TexSlot.use_map_alpha = True
    				TexSlot.use_map_color_diffuse = False
    				TexSlot.texture_coords = 'UV'
    				if OpacityMode == 'TEX': TexSlot.alpha_factor = LayerOpacity
    				elif OpacityMode == 'MAT': TexSlot.blend_type = 'MULTIPLY'
    		
    		if not Active.material_slots:
    			bpy.ops.object.material_slot_add()
    		
    		Active.material_slots[0].material = Mat
    
    
    	Z = 0
    	global LayerNum
    	LayerNum = 0
    	LayerFlags = {}
    	LayerList = []
    	
    	for Layer in IMGs:
    		Make3DLayer(\
    		Layer['LayerName'].replace(' ', '_'),\
    		Layer['LayerNameShort'].replace(' ', '_'),\
    		Z,\
    		Layer['LayerCoords'],\
    		Layer['RenderLayer'],\
    		Layer['LayerMode'],\
    		Layer['LayerOpacity'],\
    		Layer['HasAlpha'],\
    		)
    		
    		Z -= LayerOffset
    	
    	if SetupCompo:
    		#-------------------------------------------------
    		# COMPO NODES
    		
    		Scene.use_nodes = True
    		
    		Tree = Scene.node_tree
    		
    		for i in Tree.nodes:
    			Tree.nodes.remove(i)
    		
    		LayerList.reverse()
    		
    		Offset = 0
    		LayerLen = len(LayerList)
    		
    		for Layer in LayerList:
    			
    			Offset += 1
    			
    			X_Offset = (500*Offset)
    			Y_Offset = (-300*Offset)
    			
    			Node = Tree.nodes.new('R_LAYERS')
    			Node.location = (-500+X_Offset, 300+Y_Offset)
    			Node.name = 'R_'+ str(Offset)
    			Node.scene = Scene
    			Node.layer = Layer[0]
    			
    			if LayerViewers:
    				Node_V = Tree.nodes.new('VIEWER')
    				Node_V.name = Layer[0]
    				Node_V.location = (-200+X_Offset, 200+Y_Offset)
    				
    				Tree.links.new(Node.outputs[0], Node_V.inputs[0])
    			
    			if LayerLen > Offset:
    				
    				Mode = LayerList[Offset][1] # has to go one step further
    				LayerOpacity = LayerList[Offset][2]
    				
    				if not Mode in ('Normal', '-1'):
    					
    					Node = Tree.nodes.new('MIX_RGB')
    					if OpacityMode == 'COMPO': Node.inputs['Fac'].default_value[0] = LayerOpacity
    					else: Node.inputs['Fac'].default_value[0] = 1
    					Node.use_alpha = True
    					
    					if Mode in ('Addition', '7'): Node.blend_type = 'ADD'
    					elif Mode in ('Subtract', '8'): Node.blend_type = 'SUBTRACT'
    					elif Mode in ('Multiply', '3'): Node.blend_type = 'MULTIPLY'
    					elif Mode in ('DarkenOnly', '9'): Node.blend_type = 'DARKEN'
    					elif Mode in ('Dodge', '16'): Node.blend_type = 'DODGE'
    					elif Mode in ('LightenOnly', '10'): Node.blend_type = 'LIGHTEN'
    					elif Mode in ('Difference', '6'): Node.blend_type = 'DIFFERENCE'
    					elif Mode in ('Divide', '15'): Node.blend_type = 'DIVIDE'
    					elif Mode in ('Overlay', '5'): Node.blend_type = 'OVERLAY'
    					elif Mode in ('Screen', '4'): Node.blend_type = 'SCREEN'
    					elif Mode in ('Burn', '17'): Node.blend_type = 'BURN'
    					elif Mode in ('Color', '13'): Node.blend_type = 'COLOR'
    					elif Mode in ('Value', '14'): Node.blend_type = 'VALUE'
    					elif Mode in ('Saturation', '12'): Node.blend_type = 'SATURATION'
    					elif Mode in ('Hue', '11'): Node.blend_type = 'HUE'
    					elif Mode in ('Softlight', '19'): Node.blend_type = 'SOFT_LIGHT'
    					else: pass
    					
    				else:
    					Node = Tree.nodes.new('ALPHAOVER')
    					if OpacityMode == 'COMPO': Node.inputs['Fac'].default_value[0] = LayerOpacity
    				Node.name = 'M_' + str(Offset)
    				Node.location = (300+X_Offset, 250+Y_Offset)
    				
    				if MixerViewers:
    					Node_V = Tree.nodes.new('VIEWER')
    					Node_V.name = Layer[0]
    					Node_V.location = (500+X_Offset, 350+Y_Offset)
    					
    					Tree.links.new(Node.outputs[0], Node_V.inputs[0])
    				
    			else:
    				Node = Tree.nodes.new('COMPOSITE')
    				Node.name = 'Composite'
    				Node.location = (400+X_Offset, 350+Y_Offset)
    				
    		Nodes = bpy.context.scene.node_tree.nodes
    		
    		if LayerLen > 1:
    			for i in range (1, LayerLen+1):
    				if i == 1:
    					Tree.links.new(Nodes['R_'+str(i)].outputs[0], Nodes['M_'+str(i)].inputs[1])
    				if 1 < i < LayerLen:
    					Tree.links.new(Nodes['M_'+str(i-1)].outputs[0], Nodes['M_'+str(i)].inputs[1])
    				if 1 < i < LayerLen+1:
    					Tree.links.new(Nodes['R_'+str(i)].outputs[0], Nodes['M_'+str(i-1)].inputs[2])
    				if i == LayerLen:
    					Tree.links.new(Nodes['M_'+str(i-1)].outputs[0], Nodes['Composite'].inputs[0])
    		else:
    			Tree.links.new(Nodes['R_1'].outputs[0], Nodes['Composite'].inputs[0])
    		
    		for i in Tree.nodes:
    			i.location[0] += -250*Offset
    			i.location[1] += 150*Offset
    
    #------------------------------------------------------------------------
    import os
    import bpy
    from bpy.props import *
    from math import pi
    
    # Operator
    class GIMPImageToScene(bpy.types.Operator):
    	''''''
    	bl_idname = "import.gimp_image_to_scene"
    	bl_label = "GIMP Image to Scene"
    	bl_description = "Imports GIMP multilayer image files into 3D Scenes"
    	bl_options = {'REGISTER', 'UNDO'}
    	
    	filename = StringProperty(name="File Name",
    		description="Name of the file")
    	directory = StringProperty(name="Directory",
    		description="Directory of the file")
    	
    	LayerViewers = BoolProperty(name="Layer Viewers",
    		description="Add Viewer nodes to each Render Layer node",
    		default=True)
    	
    	MixerViewers = BoolProperty(name="Mixer Viewers",
    		description="Add Viewer nodes to each Mix node",
    		default=True)
    	
    	PremulAlpha = BoolProperty(name="Premuliply Alpha",
    		description="Set Image and Render settings to premultiplied alpha",
    		default=True)
    
    	ShadelessMats = BoolProperty(name="Shadeless Material",
    		description="Set Materials as Shadeless",
    		default=True)
    	
    	OpacityMode = EnumProperty(name="Opacity Mode",
    		description="Layer Opacity management",
    		items=(
    			('TEX', 'Texture Alpha Factor', ''),
    			('MAT', 'Material Alpha Value', ''),
    			('COMPO', 'Mixer Node Factor', ''),
    			('BAKE', 'Baked in Image Alpha', '')),
    		default='TEX')
    	
    	SetCamera = BoolProperty(name="Set Camera",
    		description="Create an Ortho Camera matching image resolution",
    		default=True)
    		
    	SetupCompo = BoolProperty(name="Setup Node Compositing",
    		description="Create a compositing node setup (will delete existing nodes)",
    		default=False)
    	
    	GroupUntagged = BoolProperty(name="Group Untagged",
    		description="Layers with no tag go to a single Render Layer",
    		default=False)
    	
    	LayerOffset = FloatProperty(name="Layer Separation",
    		description="Distance between each 3D Layer in the Z axis",
    		min=0,
    		default=0.01)
    	
    	LayerScale = FloatProperty(name="Layer Scale",
    		description="Scale pixel resolution by Blender units",
    		min=0,
    		default=0.01)
    	
    	def draw(self, context):
    		layout = self.layout
    		box = layout.box()
    		box.label('3D Layers:', icon='SORTSIZE')
    		box.prop(self, 'SetCamera', icon='OUTLINER_DATA_CAMERA')
    		box.prop(self, 'OpacityMode', icon='GHOST')
    		if self.OpacityMode == 'COMPO' and self.SetupCompo == False:
    			box.label('Tip: Enable Node Compositing', icon='INFO')
    		box.prop(self, 'PremulAlpha', icon='IMAGE_RGB_ALPHA')
    		box.prop(self, 'ShadelessMats', icon='SOLID')
    		box.prop(self, 'LayerOffset')
    		box.prop(self, 'LayerScale')
    		box = layout.box()
    		box.label('Compositing:', icon='RENDERLAYERS')
    		box.prop(self, 'SetupCompo', icon='NODETREE')
    		if self.SetupCompo:
    			box.prop(self, 'GroupUntagged', icon='IMAGE_ZDEPTH')
    			box.prop(self, 'LayerViewers', icon='NODE')
    			box.prop(self, 'MixerViewers', icon='NODE')
    	
    	def execute(self, context):
    		# File Path
    		filename = self.filename
    		directory = self.directory
    		
    		# Settings
    		LayerViewers = self.LayerViewers
    		MixerViewers = self.MixerViewers
    		OpacityMode = self.OpacityMode
    		PremulAlpha = self.PremulAlpha
    		ShadelessMats = self.ShadelessMats
    		SetCamera = self.SetCamera
    		SetupCompo = self.SetupCompo
    		GroupUntagged = self.GroupUntagged
    		LayerOffset = self.LayerOffset
    		LayerScale = self.LayerScale
    		
    		Ext = None
    		if filename.endswith('.xcf'): Ext = '.xcf'
    		elif filename.endswith('.xjt'): Ext = '.xjt'
    		
    		# Call Main Function
    		if Ext:
    			main(filename, directory, LayerViewers, MixerViewers, LayerOffset,\
    				LayerScale, OpacityMode, PremulAlpha, ShadelessMats,\
    				SetCamera, SetupCompo, GroupUntagged, Ext)
    		else:
    			self.report({'ERROR'},"Selected file wasn't valid, try .xcf or .xjt")
    		
    		return {'FINISHED'}
    
    	def invoke(self, context, event):
    		wm = bpy.context.window_manager
    		wm.fileselect_add(self)
    
    		return {'RUNNING_MODAL'}
    
    
    # Registering / Unregister
    def menu_func(self, context):
    	self.layout.operator(GIMPImageToScene.bl_idname, text="GIMP Image to Scene (.xcf, .xjt)", icon='PLUGIN')
    
    
    def register():
    	bpy.types.INFO_MT_file_import.append(menu_func)
    
    
    def unregister():
    	bpy.types.INFO_MT_file_import.remove(menu_func)
    
    
    if __name__ == "__main__":
    	register()