Saturday, May 31, 2025

Sketches faces

 








Happy Sketching!


Thursday, May 29, 2025

doodle python class observer design pattern with plotting data example

this is still a work in progress. but the idea was to use object oriented observer design pattern in an example. this one has an AnalysisFactory object communicating with Data objects when they should plot themselves.  there may be bugs so please modify/use at your own risk.

this was the result:


import numpy as np
from matplotlib import pyplot

class BaseData(object):
    def __init__(self, dataPath='', data=None):
        self._dataPath = dataPath #where to find data. supports a path to example database, csv, json 
        self._data = data #optional provide actual data to object like for NUMPYData, PYLISTData subclasses
    def doPlot(self, msg, ax=None):
        """
        Args:
            msg (str) message
            ax (matplotlib.axes.AxesSubplot) pyplot subplot object to use for adding plot
        """
        print("doing plot with message '{}'".format(msg))
        print("using raw data", self._data)
        
    def toNUMPYMatrix(self, msg):
        print("converting data to numpy matrix. assumes all numbers data {}".format(msg))
        return []

class CSVData(BaseData):
    pass

class SQLITEData(BaseData):
    pass

class NUMPYData(BaseData):
    def __init__(self, data):
        super(NUMPYData, self).__init__(data=data)

    def doPlot(self, msg, ax):
        print("class {0} doing plot with message '{1}'".format(self.__class__.__name__, msg))
        print("using raw data", self._data)
        #putting plot code here
        ax.plot(self._data)
        #pyplot.show()
        
class JSONData(BaseData):
    pass

class PYLISTData(BaseData):
    def __init__(self, data):
        super(PYLISTData, self).__init__(data=data)

    def doPlot(self, msg, ax):
        print("class {0} doing plot with message '{1}'".format(self.__class__.__name__, msg))
        print("using raw data", self._data)
        ax.plot(self._data)
        #pyplot.show()
        
class AnalysisFactory(object):
    def __init__(self):
        self._data = []
    
    def addData(self, dataNode):
        self._data.append(dataNode)
        
    def removeData(self, dataNode):
        self._data.remove(dataNode)
        
    def doPlots(self, msg):
        numFigures = len(self._data)
        if not numFigures:
            return
            
        #make figure to hold all plots
        fig, ax = pyplot.subplots(nrows=1, ncols=numFigures)
        if len(self._data) > 1:
            for i, data in enumerate(self._data):
                #print(type(ax[i]))
                data.doPlot(msg, ax[i])
        else:
            #support single plot
            data = self._data[0]
            data.doPlot(msg, ax)
            
        #show completed figure
        pyplot.show()
        
    def toNUMPYMatrix(self, msg):
        matrices = []
        for data in self._data:
            matrices.append(data.toNUMPYMatrix())

listData = PYLISTData(data=[1,2,3])
npData = NUMPYData(data=np.array([[1,2,3],[4,5,6]]))

analysis = AnalysisFactory()
analysis.addData(listData)
analysis.addData(npData)
analysis.doPlots("sending make plot update")

#class PYLISTData doing plot with message 'sending make plot update'
#('using raw data', [1, 2, 3])
#class NUMPYData doing plot with message 'sending make plot update'
#('using raw data', array([[1, 2, 3],
#       [4, 5, 6]])) 

Thanks for looking 

Wednesday, May 28, 2025

learning python scripting in Unreal Engine for Artists

i'm still very much a beginner in python scripting in Unreal Engine but thought these personal work python snippets i made may be helpful for learning.  there may be bugs and better ways to code them so please modify/use at your own risk.


import unreal

import logging

logger = logging.getLogger(__name__)

logging.basicConfig(level=logging.DEBUG)


print("yaaay running a script")


def doIt():

#addCamera()

#addBoneActor()

#translateActor("TestCylinder", translateY=0.0)


#getCameras()

#getCameraPosition()


#translateExistingCamera()

#debug()

#setMaterialAllStaticMeshes(materialName="/Engine/VREditor/UI/FrameMaterial.FrameMaterial")

#setMaterialAllStaticMeshes()


#debug()

#printKeyFramesControl()


#???translateControlRig()

#createFkControl()

#applyMaterial()


#createMaterial()

#addCubeToLevelSequence()


#printStaticActorsInOutliner()


#printStaticActorsInFocusedLevelSequence()


def debug():

#print("material" in dir(unreal.StaticMeshActor))

print(dir(unreal.MovieSceneScriptingFloatChannel))



def printStaticActorsInOutliner():

print("yaaay printing stuff")

pass


actorSystem = unreal.get_editor_subsystem(unreal.EditorActorSubsystem)

actors = actorSystem.get_all_level_actors()

meshActors = [act.get_actor_label() for act in actors if isinstance(act, unreal.StaticMeshActor)]


print(meshActors)




def printStaticActorsInFocusedLevelSequence():

print("yaay static actors in focused level sequence")

levelSequence = unreal.LevelSequenceEditorBlueprintLibrary.get_current_level_sequence()


print(levelSequence, type(levelSequence))

#LogPython: <Object '/Game/TestA_LS.TestA_LS' (0x000008A280176680) Class 'LevelSequence'> <class 'LevelSequence'>


#get static mesh actors in this level sequence

#help(levelSequence)


staticMeshActors = []


#need to use binding

rootBindings = levelSequence.get_bindings()

for binding in rootBindings:

print(type(binding)) #LogPython: <class 'MovieSceneBindingProxy'>

actorName = binding.get_name()

print(actorName)


bindingClass = binding.get_possessed_object_class()

print(bindingClass)

print(type(bindingClass))

print(bindingClass.get_name())

#only store static meshes

if not bindingClass.get_name() == "StaticMeshActor":

continue

staticMeshActors.append(actorName)

print(staticMeshActors)

return staticMeshActors


def addCubeToLevelSequence():

#add a cube static mesh to an existing level sequence


#change these to where to find level sequence

folderName = '/Game/testSequences'

levelSequenceName = 'testShot_a'

#change this to what name of cube static mesh is in outliner

meshName = "Cube" 

levelSequence = unreal.load_asset("{0}/{1}".format(folderName, levelSequenceName))


print(type(levelSequence)) #LevelSequence


#find static mesh actor

actorSystem = unreal.get_editor_subsystem(unreal.EditorActorSubsystem)

actors = actorSystem.get_all_level_actors()

meshActors = [act for act in actors if isinstance(act, unreal.StaticMeshActor) and act.get_actor_label() == meshName]


if not meshActors:

return


meshActor = meshActors[0]

unreal.log(type(meshActor)) #StaticMeshActor


#add static mesh actor to level sequence

levelSequenceSystem = unreal.get_editor_subsystem(unreal.LevelSequenceEditorSubsystem)

bindings = levelSequenceSystem.add_actors([meshActor])


#inspired by dev dot epicgames dot com : Python Scripting in Sequencer






def createMaterial():

#create a green material

#create base material

matName = "testGreenMat" #name of material

location = "/Game/testMaterials" #assumes this already exists. it is where to save material


assetTools = unreal.AssetToolsHelpers.get_asset_tools()

material = assetTools.create_asset(matName, 

location,

unreal.Material,

unreal.MaterialFactoryNew()) #returns material object


#material = unreal.load_asset("/Game/testMaterials/testGreenMat")


#create constant 3 vector

constantNode = unreal.MaterialEditingLibrary.create_material_expression(material,

unreal.MaterialExpressionConstant3Vector,

-400, 

200)


#change to green constant and plug it into base color

constantNode.constant = unreal.LinearColor(0,1,0)


unreal.MaterialEditingLibrary.connect_material_property(constantNode,

"",

unreal.MaterialProperty.MP_BASE_COLOR)

#save

unreal.MaterialEditingLibrary.recompile_material(material)


#inspired by TomCic on Unreal Engine developer forum: forums dot unrealengine dot com




def applyMaterial(materialName = "/Game/testMaterials/testMatYellow"):

#apply an existing material to selected static mesh

material = unreal.load_asset(materialName)

print(type(material))


actorSystem = unreal.get_editor_subsystem(unreal.EditorActorSubsystem)

actors = actorSystem.get_selected_level_actors()


if not actors:

return


mesh = actors[0]

if not isinstance(mesh, unreal.StaticMeshActor):

unreal.log("requires a selected static mesh actor")

return


meshComponent = mesh.get_component_by_class(unreal.StaticMeshComponent)

unreal.log("meshComponent:{}".format(meshComponent))

meshAsset = meshComponent.get_editor_property("static_mesh")

unreal.log("meshAsset:{}".format(meshAsset))

unreal.log("type meshAsset")

unreal.log(type(meshAsset)) #StaticMesh

meshAsset.set_material(0, material) #using 0 material index




def createFkControl():

#creating fk control on existing control rig

rigs = unreal.ControlRigBlueprint.get_currently_open_rig_blueprints()


print("open rigs:",rigs)

#LogPython: open rigs: ["/Script/ControlRigDeveloper.ControlRigBlueprint'/Game/simple_leg_scene_CtrlRig.simple_leg_scene_CtrlRig'"]


#print(type(rigs[0]))  # <class 'ControlRigBlueprint'>


#controller = rigs[0].get_controller()

#print(controller)

#print(type(controller)) #<class 'RigVMController'>


controller = rigs[0].get_hierarchy_controller()

#print(controller)

#print(type(controller)) #<class 'RigHierarchyController'>



controlSetting = unreal.RigControlSettings()

controller.add_control('yaay_ctrl', 

unreal.RigElementKey(type=unreal.RigElementType.BONE, name='upLeg'), 

controlSetting, 

unreal.RigHierarchy.make_control_value_from_euler_transform(unreal.EulerTransform(location=[0.000000,0.000000,0.000000],rotation=[0.000000,-0.000000,0.000000],scale=[1.000000,1.000000,1.000000]))

)





#levelSequence = unreal.LevelSequenceEditorBlueprintLibrary.get_current_level_sequence()#get_focused_level_sequence()#"animMap"

#rigs = unreal.ControlRigSequencerLibrary.get_control_rigs(levelSequence)

#print("rigs:",rigs)

#print(type(rigs[0]))

#rigs[0] #ControlRigSequencerBindingProxy

#print(type(rigs[0].control_rig)) #ControlRig

#controlRig = rigs[0].control_rig


#print("controlRig")

#print(controlRig)

#print("levelSequence", levelSequence)


def translateControlRig():

#???

levelSequence = unreal.LevelSequenceEditorBlueprintLibrary.get_current_level_sequence()#get_focused_level_sequence()#"animMap"

rigs = unreal.ControlRigSequencerLibrary.get_control_rigs(levelSequence)

#print(type(rigs[0]))

#rigs[0] #ControlRigSequencerBindingProxy

#print(type(rigs[0].control_rig)) #ControlRig

controlRig = rigs[0].control_rig


print("controlRig")

print(controlRig)

print("levelSequence", levelSequence)

print(controlRig.current_control_selection())

worldTransform = unreal.ControlRigSequencerLibrary.get_control_rig_world_transform(levelSequence, controlRig, "Bone_ctrl", unreal.FrameNumber(1))

#print("world transform")

#print(worldTransform)

curTransform = unreal.ControlRigSequencerLibrary.get_local_control_rig_euler_transform(levelSequence, controlRig, "Bone_ctrl", unreal.FrameNumber(0)) #depends on value of control rig set to euler transform

print(curTransform)

unreal.ControlRigSequencerLibrary.set_local_control_rig_euler_transform(levelSequence, controlRig, "Bone_ctrl", unreal.FrameNumber(1), unreal.EulerTransform(location=[0, 0, 21]), set_key=False)

#curTransform = unreal.ControlRigSequencerLibrary.get_local_control_rig_euler_transform(levelSequence, controlRig, "Bone_ctrl", unreal.FrameNumber(0)) #depends on value of control rig set to euler transform

#print(curTransform)




def printKeyFramesControl():

#print all keyframes on a control of a control rig

logger.info("yaay - printing keyframes")


controlRigName = "cube_skinned_b_CtrlRig"

controlName = "Bone_ctrl"

attr = "Location.Y"

levelSequence = unreal.LevelSequenceEditorBlueprintLibrary.get_current_level_sequence()#get_focused_level_sequence()#"animMap"

rigs = unreal.ControlRigSequencerLibrary.get_control_rigs(levelSequence)


#print(rigs)

rig = rigs[0].control_rig

print(rig)

#<Object '/Game/cube_skinned_b_CtrlRig_Take1.cube_skinned_b_CtrlRig_Take1:MovieScene_0.MovieSceneControlRigParameterTrack_0.cube_skinned_b_CtrlRig' (0x000005BC19285400) Class 'cube_skinned_b_CtrlRig_C'>


rigTrack = rigs[0].track

print("rigTrack")

print(rigTrack)


keyedSection = rigTrack.get_section_to_key()

print("keyedSection")

print(keyedSection)


channelObjs = keyedSection.get_all_channels()#get_channel(channelName)

for channelObj in channelObjs:

print(channelObj)

print(type(channelObj))

logger.info(channelObj.get_path_name())

keys = channelObj.get_keys()

print("keys >>>")

print(keys)


for key in keys:

keyTime = key.get_time().frame_number.value


keyValue = key.get_value()


print(keyTime, keyValue)




def setMaterialAllStaticMeshes(materialName="/Engine/MaterialTemplates/Gradients/Gradient_Linear.Gradient_Linear"):

meshes = getStaticMeshes()

print(meshes)

material = unreal.load_asset(materialName)

print(material)

print(type(material))


for mesh in meshes:

meshComponent = mesh.get_component_by_class(unreal.StaticMeshComponent)

logger.info("meshComponent:{}".format(meshComponent))

meshAsset = meshComponent.get_editor_property("static_mesh")

logger.info("meshAsset:{}".format(meshAsset))

meshAsset.set_material(0, material)

def getStaticMeshes():

actorSystem = unreal.get_editor_subsystem(unreal.EditorActorSubsystem)

actors = actorSystem.get_all_level_actors()


#print(actors)

result = [x for x in actors if isinstance(x, unreal.StaticMeshActor)]


return(result)



def translateExistingCamera():

logger.info("translate a camera...")


cameras = getCameras() or []

if not cameras:

return


camera = cameras[0]


location = camera.get_actor_location()

logger.info("before cam position {}".format(location))


newLocation = unreal.Vector(location.x, location.y+100, location.z)

camera.set_actor_location(newLocation, False, False) #position, sweep, teleport


location = camera.get_actor_location()

logger.info("after cam position {}".format(location))



def getCameraPosition():

cameras = getCameras() or []

if not cameras:

return


camera = cameras[0]


location = camera.get_actor_location()

logger.info("cam position {}".format(location))


def getCameras():

actorSystem = unreal.get_editor_subsystem(unreal.EditorActorSubsystem)

actors = actorSystem.get_all_level_actors()


#print(actors)

result = [x for x in actors if isinstance(x, unreal.CineCameraActor)]

print(result)

#for a in actors:

# print(type(a))

return result


def addCamera():

logging.info("adding camera")


#add camera actor

#CineCameraActor #can get this by manually creating

actorClass = unreal.CineCameraActor

cylinderActor = unreal.EditorLevelLibrary.spawn_actor_from_class(actorClass, unreal.Vector(0,0,20), unreal.Rotator(0,0,0)) #class, translation, rotation


#add actor to level sequence

levelSystem = unreal.get_editor_subsystem(unreal.LevelSequenceEditorSubsystem) #?one per level sequence

levelSystem.add_actors([cylinderActor])



def addBoneActor():

print("add bone actor")

#loading a skeletal mesh

mesh = unreal.load_object(name="/Game/cube_skinned_b", outer=None)

factory = unreal.ControlRigBlueprintFactory

rig = factory.create_control_rig_from_skeletal_mesh_or_skeleton(selected_object=mesh)


hierarchy = rig.hierarchy

elements = hierarchy.get_all_keys()

for e in elements:

print(e)


    #LogPython: <Struct 'RigElementKey' (0x0000052EDB1D92E0) {type: Bone, name: "Bone"}>

#LogPython: <Struct 'RigElementKey' (0x0000052EDB1D63F0) {type: Bone, name: "Bone_end"}>

"""

    hierarchyCtrl = rig.get_hiearchy_controller()

    #add bone

    newBone = hierarchyCtrl.add_bone(name="testBone", parent=unreal.RigElementKey(), transform=unreal.Transform())


    #add an end bone to bone at a given offset

    newLoc = unreal.Transform(location=[0, 0, 5]) #xyz  offset

    endBone = hierarchyCtrl.add_bone(name="testEndBone", parent=newBone, transform=newLoc)

    """


def translateActor(actorName, translateY=5.0):

#shows info on finding an actor by name. and setting an actor location attribute

#unreal.Actor python docs

actorSystem = unreal.get_editor_subsystem(unreal.EditorActorSubsystem)

actors = actorSystem.get_all_level_actors()


actor = [x for x in actors if x.get_actor_label() == actorName]

if not actor:

return

actor = actor[0]


print(actor)


curLoc = actor.get_actor_location()

newLoc = unreal.Vector(curLoc.x, translateY, curLoc.z)

actor.set_actor_location(newLoc, False, False) #position, sweep, teleport



"""

def addCylinderActor():

#add an actor to scene

print("addCylinderActor")


cylinderMesh = unreal.load_asset('/Engine/BasicShapes/Cylinder') #to get path - can create a sphere and in ui gui can browse to its folder location

#actorClass = unreal.StaticMeshActor

cylinderActor = unreal.EditorLevelLibrary.spawn_actor_from_object(cylinderMesh, unreal.Vector(0,0,10), unreal.Rotator(0,0,0)) #object, translation, rotation

"""


"""

def addCylinderActor_v0():

#add an actor to scene

print("addCylinderActor")


cylinderMesh = unreal.load_asset('/Engine/BasicShapes/Cylinder') #to get path - can create a sphere and in ui gui can browse to its folder location

actorClass = unreal.StaticMeshActor

cylinderActor = unreal.EditorLevelLibrary.spawn_actor_from_class(actorClass, unreal.Vector(0,0,70), unreal.Rotator(0,0,0)) #class, translation, rotation

"""


"""

def printActors():

#print actors in scene


actorSystem = unreal.get_editor_subsystem(unreal.EditorActorSubsystem)

actors = actorSystem.get_all_level_actors()

print(actors)


def printSelectedActors():

actorSystem = unreal.get_editor_subsystem(unreal.EditorActorSubsystem)

actors = actorSystem.get_selected_level_actors()

print(actors)

print(len(actors))

unreal.log("printSelectedActors")

#print(type(actors[0]))

#LogPython: <class 'StaticMeshActor'>


#staticMeshComponent = actors[0].get_editor_property("static_mesh_component")

#print(type(staticMeshComponent))

#LogPython: <class 'StaticMeshComponent'>


def translateUpSelectedActors(amount=5):

actorSystem = unreal.get_editor_subsystem(unreal.EditorActorSubsystem)

actors = actorSystem.get_selected_level_actors()

for actor in actors:

#from unreal.Actor

actor.add_actor_world_offset((0,0,amount), False, False)


"""


#printActors()

#printSelectedActors()

#translateUpSelectedActors(amount=20)

#addCylinderActor()


doIt()


#py "C:\Users\Nathaniel\Documents\unreal_learning\dev_area\topics.py"


#inspired by

#https://forums.unrealengine.com/t/how-to-create-static-mesh-actors-in-level-using-python-script/473670/2



Thanks for looking


inspired by,

Matt Lake MattLakeTA

matthewlake dot net