Perforce: Setting up Ignore lists


Sometimes your local workspace will have files that you don't want to check in. Examples include Maya swatches files, if you are using Unity, the library folder, and anything called tmp.

You can set up P4 to ignore files and folders using the P4IGNORE environment variable, and a text file in your perforce root called .p4ignore.txt

Here is how you set it up:

An example of the contents of an ignore file. Comments are added using the # sign. 
  • Create a file in the root directory of your workspace (eg: C:/Projects/Perforce/) called .p4ignore.txt
  • Inside this file, define which file types to ignore. For example:
  • The .swatches file, which is generated by Maya. 
  • The Library folder, generated by Unity. 
  • Any other folder that contains source file work that should remain local to people's workstations (texture bakes, render data etc).
  • Once this file is set up, open the command console (windows key + r then type in cmd) and type in: p4 set P4IGNORE = .p4ignore.txt
Setting the environment variable in a windows environment. 
  • Now, Perforce should ignore the file types and folders defined in the text document. 
  • Next time an attempt to add this file is made, a warning should show up, and the files will not be added to your changelist. 

Thi

ZBrush- Goblin final sculpt and 3d print Prep

In between writing tools and prototyping a pretty sweet new project (shhh!) I've taken the goblin sculpt far enough that I'm willing to dump some dough on a 3d print. Here is the final, posed model, ready for hollowing out and sending off to the magical 3d printing machines.


The entire model, from start to finish, was created in Zbrush. It all started with a sphere, and the primary tools used were the Clay Buildup brush, clip, move and transpose toolset. I can't get enough of the clip brush. Seriously.

Posing anything in ZBrush is a bit of a pain in the ass, but the Topological masking feature of the transpose tools makes it a lot more intuitive (even if the transpose tools themselves are pretty ambiguous in function). But once you get how its meant to work its suddenly one of the most enjoyable 3d tools to use.

The basis for the clothing was created using the panel loops tool, and the belts and buckles were added using a curve brush (which is an absolute bastard to use). Finally the model was combined into a single shell by gradually combining and dynameshing the individual elements.

I'm looking forward to seeing how it turns out as an actual model!

--------
Edit:

The model is now available on Shapeways!


ZBrush Speedsculpt: Goblin!

This week's theme was 'Goblin'. Due to GDC I wasn't able to get around to actually sculpting it until this afternoon. 

Sculpt time took the full hour. Had fun with the ears!


-------------------------------------------------
Edit1:
Spent some additional time cleaning the sculpt up and giving it a body...

A well dressed goblin...

Maya: Animation Event Definition Tool

I've been working on a new set of tools to define animation event data in Maya and export it into Unity for consumption by the AssetPostProcessor. This has been kind of a cool learning experience, because before now I really didn't have much to do with the Animation pipe, which has been an entirely manual process for the animators.

Previously clips were cut up and events were defined by hand in Unity once the .fbx files had been exported from Maya. This wasn't such a bad thing, except that the tools in Unity for defining events were very un-intuitive. The aim of doing all this was to allow the animators the ability to work in a tool they were familiar with, and get the AssetPostProcessor to do most of the boring legwork on the Unity side.

The Maya interface. 
The Maya tool is pretty simple right now, and responsive enough that the animators don't hate me. Navigating to different clips or events will move to that time range on the slider. The event list is directly correlated to events called by the engineers in engine, so they are only available as pre-set items in a drop down.

The data is stored in the scene as attributes on empty nodes. On export time, the data is compiled into dictionaries that are then written into a .JSON file named after the .fbx.

The end result is something like this:

Data for an 'Attack' animation. The first clip is the entire duration, the next three are the intro, loop and outro. In the anim events the unit fires it's weapons three times, once on frame 5, then on 9 and 13. 'Index' is used for the muzzle position on a unit or turret, as those are the only entities in game making use of the system. I would prefer to be using named bones for more flexibility. 
Once this animation is out there, the engineering team pull it into the AssetPostProcessor and generate the required clips and event metadata from the contents. 

All in all, the Maya side is pretty basic at the moment, and implemented on a project that currently has pretty basic animation requirements. Even so, the idea of feeding data into the AssetPostProcessor is something that really appeals to me, and the .JSON format has been pretty easy to write to from Python. 

Eventually I would like to be able to define custom VFX events on named bones, and mark up non-event related data like whether you want an asset to automatically generate lightmap UV's on an imported model or not. There is a lot of potential there. 

ZBrush Speedsculpt: "Hydrosol" Cargo ship.

Theme this week was 'starship' so I made something up. I didn't want to have some big weapon covered star ship, so I went with a cargo freighter design.

"Hydrosol", sculpt time 50 minutes, although I took 10 minutes to sketch out a rough idea before I started.

Solids on top, liquids down the bottom. 

Zbrush Speedsculpt: Alien Pilot Guy... thing...

Hooray for Zbrush lumpy aliens! No particular theme this week, so just kinda sculpted away... Sculpted in under an hour.

Could also pass for an alien optometrist... 

Perforce: Delete empty change lists using Python

Some of the tools I've written allow a user to check out chains of files- like Maya files as well as any exported FBX files and their unity metadata etc, all in one nice pass. This is great, but it has one annoying side effect. If the user presses the button twice the files are added to another change list, but the one they were just in stays there, empty. Press it a number of times and suddenly you have an army of zombie phantom changelists whose only purpose is to clutter up your pending list and annoy you. 

I have been using the P4Python API and found it to be... well... its kinda crap. It would be great if it had a 'delete all empty pending changelists' function, but it doesn't seem to. So I wrote one of my own. 

Beware! If you don't like hacking output out of strings the following code will make you cringe... 

There's my target...
import subprocess

"""Get a list of changelists from the command line. Try to delete them (will delete if empty)"""
# sInfo= subprocess.STARTUPINFO() # Use this instead of the code below to hide the output window. Kinda handy if you don't like annoying artists.  
# sInfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW # Hide the cmd window
# p = subprocess.Popen(command, stdout=subprocess.PIPE, startupinfo=sInfo) # Same as below, but no cmd window. 

workspace = 'YourWorkspace'
# Get the pending changes on the local client using the P4 console commands and reading the output.
command = "p4 changes -s pending -c %s" % workspace 
p = subprocess.Popen(command, stdout=subprocess.PIPE) 
temp = p.stdout.read()

# Split the block of text at the line endings. This should give you one changelist per line. 
raw_data = temp.split('\n') 

print raw_data

# Now go through each line and split the text at the spaces. 
# This should end up with something that reads like ['Change', '99999', 'on' etc etc...
for line in raw_data: 
    target = line.rstrip().split(" ")
    if len(target) > 1: # Skip any list with single elements. That aint got what we want. 
        changeNum = target[1] # The changeNum should be the second element
        command = 'p4 change -d %s' % (changeNum) # Attempt to delete the changelist. P4 refuses to delete changelists with items.  
        p = subprocess.Popen(command, stdout=subprocess.PIPE) # Lets get some info back again. 
        temp = p.stdout.read() # Tell us about what you just did. 
        print temp # Good boy. 

The Result... poor 76610 got what was coming to him...

Output will be something like this:
["Change 76610 on 2014/02/06 by ****@**** *pending* '[EmptyChangeListToNuke] '\r", 
"Change 76607 on 2014/02/06 by ****@**** *pending* '[ToolDev] Stuff '\r", '']

Change 76610 deleted.
Change 76607 has 35 open file(s) associated with it and can't be deleted.