Thursday, October 16, 2025

Unreal Engine control rig blendshape doodle using Blender blendshapes

i'm still very new to Unreal Engine's control rig but thought this doodle may be helpful for learning.  there may be better ways to implement.

here is an example of driving 4 blendshapes (the blendshapes were created in Blender and exported to fbx so they could be imported into Unreal Engine):


here is a picture of the control rig graph for a simpler example driving 2 blendshapes.  similar logic can be used by copying and pasting these nodes and changing up the blendshape names and driving transformation channel to get it to work for 4 blendshapes.

here is a picture of the control rig graph that has the various nodes used to drive 2 blendshapes.


basically starting left to right:

on far left is the animator control that will be used to drive the blendshapes.

next it uses a 'Greater' node to decide if the controls transform z channel is positive or negative. here the z axis of the control will be used to drive 2 blendshapes.  if the z translate axis is positive it uses its value after clamping it to a number between 0 and 1 to drive the first blendshape which is set in the 'set curve value' node. if the control's z is negative it first multiplies its value by -1 to get a positive number then it also eventually clamps its value and sends it to the second blendshape 'set curve value' node. (some of the float multiplies was to tweak the sensitivity of how much the animator control moves is enough to turn on blendshapes).

Hope this is helpful.

Happy Sketching!


also i highly recommend checking out JC's YouTube channel for learning about control rig.

inspired by,

JC's '3D Education with JC' YouTube channel's 'Build a control rig from scratch' video

Saturday, August 30, 2025

Illustrator javascript doodle color shapes and export layers to png

this is a simple doodle in Illustrator using javascript that has an example of creating functions, coloring shapes with a fill color, and exporting layers to png.  i'm still new to javascript so this example doesn't have a ui yet.  there may be bugs or better ways to implement so please use modify at your own risk.



//a simple tool to color all shapes in illustrator document and then export each layer to png


//utility methods
function getLayersVisibilityDict(doc)
{
	/*
	Args:
		doc (document object)
	Returns:
		(dictionary): keys int indexes values bool for whether layer is visible
	*/
	var result = {};
	for(var i=0; i<doc.layers.length; i++)
	{
		result[i] = doc.layers[i].visible;
	}

	return result;
}

function setLayersVisibilityByDict(doc, data)
{
	/*
	Args:
		doc (document object)
		data (dictionary): keys are layer index value is visiblity to set to
	*/
	for(var i=0; i<doc.layers.length; i++)
	{
		doc.layers[i].visible = data[i];
	}
}
//end utility methods


//color all shapes
function colorAllShapes(r, g, b)
{
	/*
	Args:
		r (int) red rgb value
		g (int) green rgb value
		b (int) blue rgb value
	*/

	//requires setting all layers visible first.

	alert("coloring all shapes");

	//get reference to active document
	var doc = app.activeDocument;

	layerVisibilityDict = getLayersVisibilityDict(doc); //starting layer visiblity

	//make all layers visible
	for(var i=0; i<doc.layers.length; i++)
	{
		doc.layers[i].visible = true;
	}

	//loop all paths
	for(var i=0; i<doc.pathItems.length; i++)
	{
		shape = doc.pathItems[i];
		color = new RGBColor();
		color.red = r;
		color.green = g;
		color.blue = b;
		//fill shape with color
		shape.fillColor = color;
		//ensure shape has fill
		shape.filled = true;
	}

	//restore layer visibility
	setLayersVisibilityByDict(doc, layerVisibilityDict);
}



//function that acts as a constructor. for older illustrator that doesnt have class available
function LayerExporter(){
	/*responsible for exporting illustrator layers to individual png files
	*/
	
	this.doc = app.activeDocument;

	//export each layer to individual png files
	this.doIt = function()
	{
		var doc = this.doc;
		if(!doc)
		{	
			alert("no active document");
			return;
		}

		//todo get export folder from artist
		//var exportDir = "/Users/Nathaniel/Desktop/learning_/illustrator_dev_testing/coloringShapes";

		var exportFolder = Folder.selectDialog("Select a folder to export layers to");
		//new Folder(exportDir);

		if(!exportFolder)
		{
			alert("no export folder");
			return;
		}

		//export options
		var exportOptions = new ExportOptionsPNG24();
		exportOptions.antiAliasing = true; //enable anti aliasing
		exportOptions.transparency = true; //preserve transparency
		exportOptions.artBoardClipping = true; //if false it might export stuff outside art clip board
		exportOptions.horizontalScale = 100; //100 pct scale
		exportOptions.verticalScale = 100; //100 pct scale


		//store starting layer visibility
		const layersVisiblityDict = getLayersVisibilityDict(this.doc);

		//iterate through each layer
		for(var i=0; i<doc.layers.length; i++)
		{
			var currentLayer = doc.layers[i];
			//hide all other layers
			this.hideAllLayersExceptIndex(i);

			//construct file name
			var exportFileName = currentLayer.name+".png";
			var exportFileObj = new File(exportFolder.fsName + "/" + exportFileName);

			//export current visible layer
			doc.exportFile(exportFileObj, ExportType.PNG24, exportOptions);
		}
		
		//restore visibility of layers
		setLayersVisibilityByDict(this.doc, layersVisiblityDict);
	}


	this.hideAllLayersExceptIndex = function(indexShow)
	{
		/*
		Args:
			indexShow (int): the index to make visible
		*/
		var doc = this.doc;

		for(var i=0; i<doc.layers.length; i++)
		{
			doc.layers[i].visible = (i == indexShow); //google searched tip to shorten code. it gives false most of time except when counter is index
		}
	}

}

function doIt()
{
	//hard coded color
	colorAllShapes(r=0, g=0, b=255);


	//exporting layers
	var layerExporter = new LayerExporter();
	layerExporter.doIt();
}

doIt();

 

Thanks for looking

Wednesday, August 13, 2025

ZBrush zscript doodle add reference image

simple ZBrush zscript to add a spotlight reference jpeg image to ZBrush.  there may be bugs so please modify use at your own risk.


 

//simple ZBrush script to add a reference jpeg image to opened scene


[RoutineDef, addRefImage,
	//get texture file from user. only supporting jpeg
	[VarSet, texturePath, [FileNameAsk, "JPG(*.jpg)",,"Please select jpeg texture file to import"]]
	//[VarSet, texturePath, "!:/Users/Nathaniel/Desktop/learning_/zbrush_dev_testing/b_tex.jpg"]

	//set texture file as next file path to possibly import
	[FileNameSetNext, texturePath]

	//import texture
	[IPress, Texture:Import]

	//extract file name from texture full path
	[VarSet, fileName, [FileNameExtract, texturePath, 2]]
	//[Note, fileName]

	[IPress, [StrMerge, "Texture:", fileName]]//[IPress, Texture:texture]
	[IPress, Texture:Add To Spotlight]

	//turn off samples spotlight projection
	[IUnPress, Brush:Samples:Spotlight Projection]

	//argument to method
	,msg
]

[IButton, addReferenceImage, "add reference image using spotlight",
	//call method
	[VarSet, msg, "doodle"]
	[RoutineCall, addRefImage, msg]
] 
//Happy Sketching!