Nathaniel Anozie
Saturday, May 31, 2025
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