Wiki

PaulsLittleHelpers

Da Vinci

Features

The UE4 Export Tool has been built for artists that want to export their models perfectly fit for UE4. The tool does all the time consuming work like making custom Lightmap UVs, removing obsolete material slots, renaming and the standard actions like freezing transformations and deleting history. The tool works in combination with the other tools in the toolbox, like LOD Groups & LOD Imposters.


Q: Why would I need to make custom lightmap UVs, UE4 does that for you?!
A: Correct, but UE4 adds way too much padding between generated sub-optimal UV maps. This results in a requirement of higher Lightmap Resolution increasing the memory footprint. This tool however uses the trusted generation methods from Maya.


Q: I dont use UE4, can I also use this for Unity?
A: Yes, the tool has been tweaked for UE4, but it also works in your Unity5+ pipeline.


The LOD Groups tool takes all selected objects, and creates a LOD Group from it. The tool will determine the LOD level depending on the polycount. Having a High-Poly and a Low-Poly selected will automatically set the object with the highest polycount to LOD0. The user is also able to specify LOD Threshold distances for the meshes; This is done by writing distances in the "Threshold Distances" textbox, with each distance separated by a comma.


Q: Does the order in which I select my objects in the scene matter?
A: No, the tool will order the LOD levels depending on the objects their polycount.


Q: Can I afterwards still manually tweak the LOD Group?
A: Yes, just select the LOD group in the outliner, and re-order or add/remove objects from the group to your preference. Same goes for other parameters, just change them in the attribute editor.


The LOD Imposters tool is currently still in the development phase, and is therefore locked from usage.


The LOD Imposters tool creates imposter cards from the selected model. It renders texture atlasses per PBR texture. (Diffuse, RoughnessAoMetallic (packed), and Normal Map). The atlas will contain x amount of frames, determined by the "Number of Frames" parameter. The total size of the atlas is determined by the "Atlas Size" parameter. Please note that by requesting more frames, the individual frame resolution gets lower.


Q: How do I use it?
A: The Imposter card gets automatically added to the LOD group of your mesh. You do however need to manually set the threshold in the application of use. (Like Unreal)


The Mesh Packer Tool takes your selection of meshes, and combines them into one. It also combines shaders attached to the selection into one. The tool therefore results in [Many meshes -> One mesh], [Many shaders -> One shader]. It takes all UV's and lays them out in a grid, sorted by shader.. And produces atlasses for the selected textures.


Q: When is the tool most effective?
A: Since the tool packs textures and UV's into a grid system, it works best if you use it on [n*n] meshes. (1, 4, 9, 16, etc)


Q: Where does the tool output the resulting assets?
A: The tool exports the resulting texture atlasses in the specified export location, but does not export your mesh.


The Channel Packer Tool allows users to merge greyscale textures into one texture to optimize the memory footprint of the asset. The tool takes up to three specified textures and places them in one of the RGB channels of the output texture. The user is currently able to import and export textures with the [JPG, PNG, TGA] format.


Q: Do I need to imput a texture in all three slots?
A: No, the user is able to input 0-3 textures. Not specifying a texture in a slot will result in that channel being empty.


Q: Do the input textures need to be greyscale?
A: Preferrably yes, but you are able to input non-greyscale textures. The tool will then just take the R channel from it.


The "In Dev" tab shows the user what features are currently being developed, and a small roadmap of what features are to be expected in the near future.


Q: Can I request features?
A: Yes! Please send your requests to plh@ambrosiussen.com


Q: How long does developing a feature take?
A: That solely depends on the complexity of the requested feature / tool. For a tool like the Channel Packer, it takes about a day.



Tool Development

PaulsLittleHelpers

PaulsLittleHelpers is a collection of tools combined in a toolbox, that automatically checks if the user is using the newest tool available. This prevents many issues like developers filing bugreports for older versions of the tool. It also ensures developers get the newest tools available to decrease their time spent on problemsolving and time consuming work, and instead get more time to be creative.


The tool has two buttons at the bottom that the user can press should there be a problem, or for any questions. The "@" button opens up a contact form to email the developer, and the "?" button opens the wiki with the FAQ.


Just copy the script below and run it in Maya (Also save it on your tool-shelf for easy access).
Or Click HERE to download the toolbox.


#### PaulsLittleHelpers
##   
##    Author: Paul Ambrosiussen
##    Date Created: 01-07-2016
##    Questions & Support: paul@ambrosiussen.com
##
#### PaulsLittleHelpers

#IMPORT ALL REQUIRED LIB
#-----------------------
import sys, os, urllib2, zipfile
import maya.cmds as cmds

#### FOR POWER USERS, SPECIFY CUSTOM LOCATION ####
CustomDirectory = 'C:/PaulsLittleHelpers'
#### ---------------------------------------- ####

#Check user directory formatting
if CustomDirectory[-1] != '/':
	CustomDirectory+= '/'

#Function to return version number online copy
def GetVersionNumberOnline():
	return int(urllib2.urlopen('http://ambrosiussen.com/downloads/pyTools/tools/version.txt').read())

#Function to return version number local copy
def GetVersionNumberLocal():
	return int(open(CustomDirectory + 'version.txt').read())

#Function to check if directory exists
def DoesDirectoryExist(a_dirLocation):
	return os.path.exists(a_dirLocation)

#Function to check if version file exists
def DoesVersionFileExist(a_dirLocation):
	return os.path.isfile(a_dirLocation+'version.txt')

#Function to create directory on provided location
def MakeDirectory(a_dirLocation):
	os.makedirs(a_dirLocation)

#Function to return 'has internet?'
def HasActiveInternetConnection():
	try:
		response = urllib2.urlopen('http://google.com',timeout=1)
		return True
	except urllib2.URLError as err: pass

	return False

#Function to display no internet popup
def NoInternetPopup():
    window = cmds.window( title='Error: No Internet Connection', iconName='Error', widthHeight=(450, 140), mnb=0, mxb=0, s=0 )
    cmds.columnLayout( adjustableColumn=1 )
    cmds.text( label='\nTo download this tool you need an active internet connection, or get a local copy.', ww=1, fn='boldLabelFont' )
    cmds.showWindow( window )

#Function to get latest tool version from server
def GetLatestToolVersion():
	t_zipLocation = CustomDirectory+'PaulsLittleHelpers.zip'

	try:
		#Download and save zipfile to disk
		t_zipFile = urllib2.urlopen('http://ambrosiussen.com/downloads/pyTools/tools/download.php?dl=1&file=plh&us=0')
		output = open(t_zipLocation,'wb')
		output.write(t_zipFile.read())
		output.close()

		#Unzip saved file to user specified location
		with zipfile.ZipFile(t_zipLocation) as zf:
			zf.extractall(CustomDirectory)

		#Cleanup downloaded zip file
		os.remove(t_zipLocation)

	except urllib2.URLError as err:
		NoInternetPopup()
		sys.exit()

def RunToolBox():
	#Add custom script location
	if CustomDirectory not in sys.path:
		sys.path.append(CustomDirectory)

	from Tools import ToolBox
	reload(ToolBox)

	ToolBox.run_plugin()

def MainFunction():
	t_activeConnection = False

	if HasActiveInternetConnection():
		t_activeConnection = True

		#Check if users local copy is latest version
		if DoesDirectoryExist(CustomDirectory) and DoesVersionFileExist(CustomDirectory):
			#Check version number
			if GetVersionNumberLocal() < GetVersionNumberOnline():

				#UPDATE
				urllib2.urlopen('http://ambrosiussen.com/downloads/pyTools/tools/download.php?us=1&file=plh')
				#Download latest version tool
				cmds.warning( 'USER HAS OLD VERSION, DOWNLOADING LATEST' )
				GetLatestToolVersion()
				
			else:
				#TOOL BEING USED
				cmds.warning( 'USER HAS LATEST, GOING TO RUN TOOL NOW' )

		else:
			#NEW DOWNLOAD
			urllib2.urlopen('http://ambrosiussen.com/downloads/pyTools/tools/download.php?us=0&file=plh')
			cmds.warning( 'FIRST TIME USE, DOWNLOADING ASSETS' )
			#Directory does not exist yet, therefore making one
			MakeDirectory(CustomDirectory)
			#Download latest version tool
			GetLatestToolVersion()

	else:
		cmds.warning( 'USER HAS NO INTERNET' )
		#Checking if user has a local copy we can run
		if not (DoesDirectoryExist(CustomDirectory) and DoesVersionFileExist(CustomDirectory)):
			NoInternetPopup()
			sys.exit()

	#Everything is set up, running tool
	if t_activeConnection: 
		urllib2.urlopen('http://ambrosiussen.com/downloads/pyTools/tools/download.php?us=2&file=plh')
	RunToolBox()

MainFunction()