Difference between revisions of "User:TomDym"

From The Foundry MODO SDK wiki
Jump to: navigation, search
 
(3 intermediate revisions by the same user not shown)
Line 692: Line 692:
 
</pre>
 
</pre>
  
=== Check if command Enabled ===
+
== Check if command Enabled ==
  
 
<pre>
 
<pre>
Line 707: Line 707:
 
     dialog = modo.dialogs.alert("Look Here", "Error: %s" % e)
 
     dialog = modo.dialogs.alert("Look Here", "Error: %s" % e)
 
lx.out('We continued on')
 
lx.out('We continued on')
 +
</pre>
 +
 +
== Get mesh from meshop ==
 +
I use this in a tool i made, that checks for mesh, then checks for a defomered mesh,. then if thats off it checks for a morphed mesh etc.
 +
Answer to: Is there any way to check a procedural mesh's mesh? I want to check if a mesh, that is getting its geo via a mesh merge, contains some specific data.
 +
I am grabbing the mesh via the sICHAN_MESH_MESH channel and using the Edit Action. I just end up getting an empty mesh.
 +
<pre>
 +
for (unsigned meshIter = 0; meshIter < outCount; meshIter++)
 +
{
 +
CLxUser_MeshService msh_srv;
 +
CLxUser_Locator mesh_locator;
 +
CLxUser_Mesh morph_mesh, deform_mesh;
 +
bool bUseDeformedMesh = false;
 +
scan.BaseMeshByIndex(meshIter, scan_mesh); // get mesh
 +
msh_srv.ItemFromMesh(scan_mesh, scan_item); // get mesh item
 +
scan.MeshInstance(meshIter, morph_mesh);
 +
// We are getting the item position, so that we can compare vert pos in world space, which the lasso falloff seems to need.
 +
CLxUser_ChannelRead read;
 +
mesh_locator.set(scan_item);
 +
scan_item.GetContext(scene);
 +
if (!scene.test())
 +
{
 +
return;
 +
}
 +
scene.GetChannels(read, time);
 +
CLxUser_ItemGraph graph;
 +
scene.GetGraph(LXsGRAPH_DEFORMERS, graph);
 +
unsigned int dfrm_count_fwd, dfrm_count_rev = 0;
 +
graph.FwdCount(scan_item, &dfrm_count_fwd);
 +
graph.RevCount(scan_item, &dfrm_count_rev);
 +
if (dfrm_count_fwd > 0 || dfrm_count_rev > 0)
 +
{
 +
if (viewevent->type == LXi_VIEWTYPE_3D)
 +
{
 +
// Todo: Presumably I can get the view from the viewevent somehow?
 +
CLxUser_View3DportService srv_vp;
 +
int idxVP = srv_vp.Current();
 +
CLxUser_View3D view;
 +
srv_vp.View(idxVP, view);
 +
// if we have deformers on, we want the deformer mesh, instead of the edit mesh.
 +
LxResult deformers = view.Deformers();
 +
if (deformers == LXe_TRUE)
 +
{
 +
// Get deformed version of the mesh.
 +
CLxUser_MeshFilter mesh_filter;
 +
CLxUser_MeshFilterIdent meshIdent_filter;
 +
read.Object(scan_item, LXsICHAN_MESH_MESH, mesh_filter);
 +
const char* ident = NULL;
 +
scan_item.Ident(&ident);
 +
mesh_filter.GetMesh(deform_mesh);
 +
if (deform_mesh.test())
 +
{
 +
bUseDeformedMesh = true;
 +
scan_mesh = deform_mesh;
 +
}
 +
}
 +
}
 +
}
 +
if (!bUseDeformedMesh)
 +
{
 +
// we have no deformers, or they are off, so now we want to see if we have a morph map selected
 +
LXtID4 morphType = LXi_VMAP_MORPH;
 +
CLxUser_VMapPacketTranslation vmap_pkt_trans;
 +
void* pkt;
 +
vmap_pkt_trans.autoInit();
 +
unsigned vmapCount = srv_sel.Count(vmapType);
 +
if (vmapCount > 0)
 +
{
 +
for (unsigned vmapIter = 0; vmapIter < vmapCount; vmapIter++)
 +
{
 +
pkt = srv_sel.ByIndex(vmapType, vmapIter);
 +
LXtID4 outVmapType;
 +
vmap_pkt_trans.Type(pkt, &outVmapType);
 +
if (outVmapType == morphType)
 +
{
 +
if (morph_mesh.test())
 +
{
 +
scan_mesh = morph_mesh;
 +
}
 +
break;
 +
}
 +
}
 +
}
 +
}
 +
</pre>
 +
 +
== Raycasting for tools from screen ==
 +
 +
<pre>
 +
CLxUser_VectorStack vector_stack (tool_vector);
 +
if (! vector_stack.test ())
 +
{
 +
    return LXe_FALSE;
 +
}
 +
 +
//
 +
// 1. Using CLxUser_Raycast
 +
//
 +
CLxUser_RaycastPacket raycast_packet {};
 +
if (! vector_stack.ReadObject (raycast_packet_offset_, raycast_packet))
 +
{
 +
    return LXe_FALSE;
 +
}
 +
 +
auto screen_event = static_cast<LXpToolScreenEvent*>(vector_stack.Read (screen_event_packet_offset_));
 +
if (! screen_event)
 +
{
 +
    return LXe_FALSE;
 +
}
 +
 +
LXtHitPolygon hit_polygon {};
 +
raycast_packet.HitPolygon (vector_stack, LXf_LAYER_ACTIVE, screen_event->fcx, screen_event->fcy, &hit_polygon);
 +
 +
//
 +
// 2. Using LXpToolHitEvent
 +
//
 +
auto hit_event = static_cast<LXpToolHitEvent*>(vector_stack.Read (hitevent_packet_offset_));
 +
if (! hit_event)
 +
{
 +
    return LXe_FALSE;
 +
}
 +
if (! hit_event->hit.pol)
 +
{
 +
    return LXe_FALSE;
 +
}
 +
 +
//
 +
// 3. Using CLxUser_View3D and CLxUser_Surface(not shown; must account for item transforms)
 +
//    I don't use modo's macro maths in practice.
 +
//
 +
CLxUser_View3DportService view_service {};
 +
const int view_index_current = view_service.Current ();
 +
 +
CLxUser_View3D view {};
 +
view_service.View (view_index_current, view);
 +
if (! view.test ())
 +
{
 +
    return LXe_FALSE;
 +
}
 +
 +
auto screen_event = static_cast<LXpToolScreenEvent*>(vector_stack.Read (screen_event_packet_offset_));
 +
if (! screen_event)
 +
{
 +
    return LXe_FALSE;
 +
}
 +
 +
const int pos_flags {0}; // alternatives: LXi_VPTO3D_SNAP; LXi_VPTO3D_WORK
 +
LXtVector point_from_screen {};
 +
if (LXx_FAIL (view.To3D (screen_event->fcx, screen_event->fcy, point_from_screen, pos_flags)))
 +
{
 +
    return LXe_FALSE;
 +
}
 +
 +
LXtVector ray_direction {};
 +
const double dist_to_point_from_ray_origin = view.EyeVector (point_from_screen, ray_direction);
 +
 +
LXtVector ray_origin {};
 +
LXx_VCPY  (ray_origin, point_from_screen);
 +
LXx_VADDS (ray_origin, ray_direction, dist_to_point_from_ray_origin * -1.0);
 +
 +
// pass ray to function that uses CLxUser_Surface::RayCast
 +
</pre>
 +
 +
== View3d Item Package drawing 2d shapes to the screen(as unlike tool you dont have access to pixel space) ==
 +
 +
<pre>
 +
int width, height;
 +
view.Dimensions(&width, &height);
 +
double xd = width - 25;
 +
double yd = height * 0.5;
 +
int sides = 6;
 +
double radius = 16;
 +
double theta = LXx_TWOPI / sides;
 +
double rad = 0.0;
 +
LXtVector vCen, xyPos;
 +
view.ToModel(xd, yd, vCen, 0);
 +
//Contour pass
 +
draw.BeginW(LXiSTROKE_LINES, COLOR_GREY, 0.8, 2.0);
 +
for (unsigned int sidecount = 0; sidecount < sides; sidecount++)
 +
{
 +
    view.ToModel((xd + cos(rad) * radius), (yd + sin(rad) * radius), xyPos, 0);
 +
    draw.Vert(xyPos, LXiSTROKE_ABSOLUTE);
 +
    rad -= theta;
 +
    view.ToModel((xd + cos(rad) * radius), (yd + sin(rad) * radius), xyPos, 0);
 +
    draw.Vert(xyPos, LXiSTROKE_ABSOLUTE);
 +
}
 +
//Fill pass
 +
draw.BeginPolygons(LXiSTROKE_TRIANGLES, COLOR_BLACK, 0.5, 1.0, 0.0, 0.0, 1, 0);
 +
for (unsigned int sidecount = 0; sidecount < sides; sidecount++)
 +
{
 +
    draw.Vert(vCen, LXiSTROKE_ABSOLUTE);
 +
    view.ToModel((xd + cos(rad) * radius*2), (yd + sin(rad) * radius), xyPos, 0);
 +
    draw.Vert(xyPos, LXiSTROKE_ABSOLUTE);
 +
    rad -= theta;
 +
    view.ToModel((xd + cos(rad) * radius * 2), (yd + sin(rad) * radius), xyPos, 0);
 +
    draw.Vert(xyPos, LXiSTROKE_ABSOLUTE);
 +
}
 +
</pre>
 +
 +
== Config - Minmising Header ==
 +
 +
<pre>
 +
<?xml version="1.0"?>
 +
<configuration>
 +
    <atom type="Frame">
 +
        <hash type="Layout" key="edit.decalPresetMaker_Layout" val="applicationLayout">
 +
          <atom type="IdealSize">670 610</atom>
 +
          <list type="Port">customview 0 1 0 1 96738922916:vp</list>
 +
          <atom type="PostRestoreCommand"></atom>
 +
          <atom type="Icon"></atom>
 +
          <atom type="InputRemappingContext"></atom>
 +
          <atom type="Tooltip"></atom>
 +
          <atom type="UserName">dpr.decalPresetMakerLayout</atom>
 +
          <atom type="SwitcherClass">normal</atom>
 +
          <atom type="SwitcherThumbnail"></atom>
 +
        </hash>
 +
       
 +
        <hash type="LayoutWindow" key="dpr.decalPresetMaker_Window">
 +
            <atom type="Title">Decal Preset Maker</atom>
 +
            <atom type="Contents">(layout) decalPresetMaker_Layout</atom>
 +
            <atom type="Size">670 610</atom>
 +
            <atom type="ShowSwitcherBar">false</atom>
 +
        </hash>
 +
       
 +
       
 +
        <hash type="customview" key="edit.96738922916:vp" val="unregistered">
 +
          <atom type="Identifier">55992922917:customview</atom>
 +
          <atom type="Server">dpr.decalPresetMaker</atom>
 +
          <atom type="ViewportLock2">0 0</atom>
 +
          <atom type="MinHeader">1</atom> <!-- This will collapse the top horizontal Title bar -->
 +
          <atom type="QuadLock">0</atom>
 +
          <atom type="ViewportTitle">Decal Preset Maker</atom>
 +
          <atom type="ViewportClass">vpapplication</atom>
 +
        </hash>
 +
    </atom>
 +
</configuration>
 +
</pre>
 +
 +
== Config - Default Value ==
 +
<pre>
 +
<?xml version="1.0"?>
 +
<configuration kit="SYZER" version="fourteen.0" and="major=14">
 +
<atom type="UserValues">
 +
    <hash type="Definition" key="sceneio.syzer.libraryfolder"><atom type="Type">string</atom><atom type="defaultvalue">Z:\Library</atom></hash>
 +
    <hash type="RawValue"  key="sceneio.syzer.libraryfolder">Z:\Library</hash>
 +
</atom>
 +
</configuration>
 +
</pre>
 +
 +
== Tool - Filtering drawing 2d and 3d ==
 +
 +
<pre>
 +
LXpToolViewEvent *viewEvent = (LXpToolViewEvent *)vec.Read(mPacketOffsets[ePacketOffset_ViewEvent]);
 +
    if (viewEvent->type == LXi_VIEWTYPE_3D){ // Draw 3d shapes}
 +
    if (viewEvent->type == LXi_VIEWTYPE_2D){ // Draw 2d shapes}
 
</pre>
 
</pre>

Latest revision as of 08:27, 21 April 2020

DoWhileUserIsIdle

//If you try to execute a script while holding down a modifier like ctrl or shift, it will postpone execution until you release the modifier
#python
import lx, lxifc
 
class visitor(lxifc.Visitor):                  
    def __init__(self):     # The initial setup method 
        pass
 
    def vis_Evaluate(self):                           
        lx.out("Visitor")

pSrv = lx.service.Platform()
vis = visitor()
com_visitor = lx.object.Unknown(vis)
pSrv.DoWhenUserIsIdle(com_visitor, lx.symbol.fUSERIDLE_MODIFIER_KEYS_UP)

//Too cancel it you need to pass exactly the same com object and flags
pSrv.CancelDoWhenUserIsIdle(com_visitor, lx.symbol.fUSERIDLE_MODIFIER_KEYS_UP )

Toggle Command

lx.eval('tool.set falloff.linear ?+')

Path of Selected Preset Item

#!python
ppaths = lxu.select.PresetPathSelection().current()
print ppaths

View3dService Example

import modo, lx

viewSvc = lx.service.View3Dport()
currentView = lx.object.View3D(viewSvc.View(viewSvc.Current()))

for i in range(viewSvc.Count()):
    view = lx.object.View3D(viewSvc.View(i))

    print view.Matrix(0)
    print view.Angles()
    print view.Axis()
    print view.EyeVector()
    lx.out(view.WorkPlane())
    a = view.To3D(150.0,150.0,2000)
    a = view.Center()
    a = view.WorkPlane()

Listeners

Navigation Listener

#python
import lx
import lxifc
import modo

class ListenerTwo(lxifc.NavigationListener):
	def __init__(self):
			self.listenerService = lx.service.Listener()
			self.listenerService.AddListener(self)
			self.item = modo.Mesh()
			self.view = lx.object.View
			lx.out('hey')

	def nav_Wheel(self,view, item):
		lx.out('Worked')
		
	def nav_Up(self, view, item):
		#is Called when move is started
		lx.out('nav_up')
		
	def nav_Move(self, view, item, hot, pos, rot, zoom):
		pass
		#is called every "move" while held down
		#lx.out('nav_move')
		
	def nav_Delta(self, view, item, hot, pos, rot, zoom):
		lx.out('nav_Delta')
		
	def nav_Down(self, view, item):
		#is Called when move is ended
		lx.out('nav_down')
		
	def nav_HotSyncPre(self, view, item):
		lx.out('nav_HotSyncPre')

	def nav_HotSyncPost(self, view, item):
		lx.out('nav_HotSyncPost')

ListenerTwo() #instance a Listener to initialize it

Mesh Listener

#python
import lx
import lxifc
import modo

geo  = modo.MeshGeometry("Mesh").internalMesh
port = lx.object.ListenerPort(geo)

class mesh_listener(lxifc.MeshListener):
	undoService = lx.service.Undo()
	def __init__(self):
		self.listenerService = lx.service.Listener()	
		self.COM_object = lx.object.Unknown(port)
		
	def ml_Changes(self, event):
		print "change"
		
l = mesh_listener()
port.AddListener(l)

Command Listener


#python
import lx
import lxifc
import modo

svc_listen = lx.service.Listener()

class CmdListener(lxifc.CmdSysListener):
	def __init__(self):
			svc_listen = lx.service.Listener()
			svc_listen.AddListener(self)
			self.armed = True
		
	def cmdsysevent_UserRedo(self):	
		#pass
		#is called everytime a redo is called
		lx.out('cmdsysevent_UserRedo')
		
	def cmdsysevent_UserUndo(self):
		#pass
		#is called everytime a undo is called
		lx.eval('log.masterClear')
		lx.out('cmdsysevent_UserUndo')
		
	def cmdsysevent_ExecutePre(self,cmd,type,isSandboxed,isPostCmd):
		if self.armed:
			cmd = lx.object.Command(cmd)
            # lx.out("'%s' will fire shortly" % cmd.Name())
			if cmd.Name() == "app.quit":
				lx.eval('replay.fileClose')

	def cmdsysevent_ExecutePost(self,cmd,isSandboxed,isPostCmd):
		if self.armed:
			cmd = lx.object.Command(cmd)
			lx.out("'%s' has finished" % cmd.Name())
		lx.out('cmdsysevent_ExecutePost')
		pass

	def cmdsysevent_RefireBegin(self):
        # we don't want a bunch of events when the user is
        # dragging a minislider or something like that,
        # so we disarm the listener on RefireBegin...
		self.armed = False

cmdListener1 = CmdListener()

Scene Item Listener

#python
import lx
import lxifc
import modo

class ListenerTwo(lxifc.SceneItemListener):
	def __init__(self):
			self.listenerService = lx.service.Listener()
			self.COM_object = lx.object.Unknown(self)
			self.listenerService.AddListener(self.COM_object)
		
	def sil_ItemAdd(self, item):
		lx.out('sil_ItemAdd')
		
	def __del__(self):
		self.listenerService.RemoveListener(self.COM_object)


list = ListenerTwo() #instance a Listener to initialize it

Selection Listener

#python
import lx
import lxifc
import modo

class ListenerTwo(lxifc.SelectionListener):
	def __init__(self):
			self.listenerService = lx.service.Listener()
			self.COM_object = lx.object.Unknown(self)
			self.listenerService.AddListener(self.COM_object)
			self.type = modo.Item.type
		
	def selevent_Add(self, type, subtType):
		lx.eval('log.MasterClear')
		lx.out('selevent_Add')
		pass
		
	def selevent_Current(self, type):
		lx.eval('log.MasterClear')
		lx.out('selevent_Current')
		pass
   
	def selevent_Remove(self, type, subtType):
		lx.eval('log.MasterClear')
		lx.out('selevent_Remove')
		pass
   
	def selevent_Time(self, time):
		lx.out(time)
		pass
   
	def selevent_TimeRange(self, type):
		pass


list = ListenerTwo() #instance a Listener to initialize it

Command System Listener

#python
import lx
import lxifc
import modo

svc_listen = lx.service.Listener()

class CmdListener(lxifc.CmdSysListener):
	def __init__(self):
			svc_listen = lx.service.Listener()
			svc_listen.AddListener(self)
			self.armed = True
		
	def cmdsysevent_UserRedo(self):	
		#pass
		#is called everytime a redo is called
		lx.out('cmdsysevent_UserRedo')
		
	def cmdsysevent_UserUndo(self):
		#pass
		#is called everytime a undo is called
		lx.eval('log.masterClear')
		lx.out('cmdsysevent_UserUndo')
		
	def cmdsysevent_ExecutePre(self,cmd,type,isSandboxed,isPostCmd):
		if self.armed:
			cmd = lx.object.Command(cmd)
            # lx.out("'%s' will fire shortly" % cmd.Name())
			if cmd.Name() == "app.quit":
				lx.eval('replay.fileClose')

	def cmdsysevent_ExecutePost(self,cmd,isSandboxed,isPostCmd):
		if self.armed:
			cmd = lx.object.Command(cmd)
			lx.out("'%s' has finished" % cmd.Name())
		lx.out('cmdsysevent_ExecutePost')
		pass

	def cmdsysevent_RefireBegin(self):
        # we don't want a bunch of events when the user is
        # dragging a minislider or something like that,
        # so we disarm the listener on RefireBegin...
		self.armed = False

cmdListener1 = CmdListener()

User Value Listener


#python
import lx
import lxifc
import modo

class ListenerTwo(lxifc.UserValueListener?):
	def __init__(self):
			self.listenerService = lx.service.Listener()
			self.COM_object = lx.object.Unknown(self)
			self.listenerService.AddListener(self.COM_object)
			self.userValue = lx.eval('user.value someValue ?')
		
	def uvl_Added(self, userValue):
		lx.out('uvl_Added')
		pass
  
	def uvl_DefChanged(self, userValue):
		lx.out('uvl_DefChanged')
		pass
 
	def uvl_Deleted(self, name):
		lx.out('uvl_Deleted')
		pass
  
	def uvl_ValueChanged(self, userValue):
		lx.out('uvl_ValueChanged')
		pass



list = ListenerTwo() #instance a Listener to initialize it

Session Listener

# python
import lx, lxifc
svc_listen = lx.service.Listener()
class sesListener(lxifc.SessionListener):
    def __init__(self):
        svc_listen = lx.service.Listener()
        svc_listen.AddListener(self)
    def sesl_SystemReady(self):
        lx.out('Session Listener: system was ready')
sesListener = sesListener()

StartCommands Config

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <atom type="StartupCommands">
        <list type="Command">sl</list>
    </atom>
 
</configuration>

Polygon Itersect Ray


import modo, lx,lxu

mesh = modo.Mesh()

for poly in mesh.geometry.polygons:
	polygon = lx.object.Polygon(poly)
	
	print polygon.Index()
	
	pos = modo.Vector3(0,0, 0.0, 0.0)
	dir = modo.Vector3(0.0, 1.0, 0.0)
	
	bool_test, hit_nrm, hit_dist = polygon.IntersectRay(pos, dir)
	
	print bool_test, hit_dist

Undo Command

import lx
import lxu

class myUndoCommand(lxu.command.BasicCommand):
    
    def basic_Execute(self, msg, flags):
        
        undo_svc = lx.service.Undo()
        if undo_svc.State() != lx.symbol.iUNDO_INVALID:
            undo_svc.Apply(myUndo(someData))

			mesh = modo.Mesh()
			with cube.geometry as geo:
				for v in geo.vertices:
					v += (0, 0.5, 0)
					
			cube.geometry.setMeshEdits()

    def cmd_Flags(self):
        return lx.symbol.fCMD_UNDO

class myUndo(lxifc.Undo):
    def __init__(self, data):
        self.data = data

    def undo_Forward(self):
        # do stuff for running command and redo
        pass
    
    def undo_Reverse(self):
        # do stuff here for undo
        pass

lx.bless(myUndoCommand, "undoCommand")

lx.object.Polygon()

#python
import modo
scene = modo.Scene()
for mesh in scene.meshes:
    poly_list = mesh.geometry.polygons.selected
    if poly_list:
        for poly in poly_list:
            lx.object.Polygon(poly)
            poly_mesh = poly.Mesh()
            scene.select(mesh, True)
    else:
        print 'For mesh %s - No Polygons Selected' % mesh.name

Selection Packets


import lx,lxu,lxifc
lx.eval('log.masterClear')

svcSel = lx.service.Selection()

type = svcSel.LookupType(lx.symbol.sSELTYP_ITEM)
name = svcSel.LookupName(type)

lx.out(name)

pkt = svcSel.Recent(type)

lx.out(pkt)

pkt = svcSel.ByIndex(type,0)

#lx.out(pkt)

n = svcSel.Count(type)
#for i in range(0,n):
#	pkt = svcSel.ByIndex(type,i)
#	lx.out('Packet: %s' % pkt)


stateFlags = svcSel.State(type,pkt)

lx.out(stateFlags)

if stateFlags and lx.symbol.f_SELECTION_PRIMARY:
	lx.out('pkt: %s' % pkt)
	

sel_type_item = svcSel.LookupType (lx.symbol.sSELTYP_ITEM)
 
# Set up a polygon selection packet translator, which lets us read information about a polygon selection packet.
item_pkt_trans = lx.object.ItemPacketTranslation (svcSel.Allocate(lx.symbol.sSELTYP_ITEM))
 
# Grab the polygon selection packet by index (0 in this case, first selected polygon).
selection_pkt = svcSel.ByIndex(sel_type_item, 0)
 
# This will get the item this polygon belongs to.
item = item_pkt_trans.Item(selection_pkt)


pkt = item_pkt_trans.Packet(item)
type_item = svcSel.LookupType (lx.symbol.sSELTYP_ITEM)
if svcSel.Test (type_item, pkt) == True:
	lx.out('selected')
	
	########################################################
	
	
lx.eval('log.masterClear')

sel_svc = lx.service.Selection ()
 
sel_type_polygon = sel_svc.LookupType (lx.symbol.sSELTYP_POLYGON)
 
# Set up a polygon selection packet translator, which lets us read information about a polygon selection packet.
polygon_pkt_trans = lx.object.PolygonPacketTranslation (sel_svc.Allocate(lx.symbol.sSELTYP_POLYGON))
 
# Grab the polygon selection packet by index (0 in this case, first selected polygon).
selection_pkt = sel_svc.ByIndex(sel_type_polygon, 0)
 
# This will get the item this polygon belongs to.
item = polygon_pkt_trans.Item(selection_pkt)

temp = item.SetName('Trial')

lx.out(temp)

Layer Scan

layer_svc = lx.service.Layer()
layer_scan = lx.object.LayerScan(layer_svc.ScanAllocate(lx.symbol.f_LAYERSCAN_EDIT))

if layer_scan.test() == False:
   return

#Some Editing Code Here

layer_scan.SetMeshChange(0, lx.symbol.f_MESHEDIT_GEOMETRY)
layer_scan.Apply()

Channels

import lxu.select
import modo

#scene = lxu.select.SceneSelection().current()
#chan_read = scene.Channels(lx.symbol.s_ACTIONLAYER_EDIT, 0.0)

#mesh = modo.Mesh()

#chan_read.set?

#lx.out(chanVal)
lx.eval('log.masterClear')
sel_svc = lx.service.Selection()
scene = item.Context()
index = item.ChannelLookup('size')


action_layer = lx.symbol.s_ACTIONLAYER_EDIT
chan_read_obj = scene.Channels (action_layer, sel_svc.GetTime())

temp = scene.Channels(action_layer,sel_svc.GetTime())
mesh = modo.Mesh()
chans = mesh.channels()

for chan in chans:
	lx.out(chan.name)
	
channelID = mesh.ChannelLookup('wsclMatrix')

# Get the Channel type   
chan_type = mesh.ChannelEvalType(channelID)

# Return the appropiate value depending on the Channel Type        
if chan_type == "float":
    lx.out(chan_read_obj.Double(mesh, channel_id))

if chan_type == "integer":
    lx.out(chan_read_obj.Integer(mesh, channel_id))

if chan_type == "string":
    lx.out(chan_read_obj.String(mesh, channel_id))

lx.out('--------------------')

matrixObject = mesh.channel('wsclMatrix').get()
matrix = modo.Matrix4(matrixObject)

mesh.scale.set(matrix.scale() * 2)

for vector in matrix.scale():
	lx.out(vector)

Command Example

import modo

class MyCommand_Cmd(lxu.command.BasicCommand):
	def __init__(self):
		lxu.command.BasicCommand.__init__ (self)
 
	def basic_ButtonName(self):
		return "My Command"
 
	def cmd_Tooltip(self):
		return "Tooltip for my command."
 
	def cmd_UserName(self):
		return "My Command Dialog"
 
	def cmd_Flags(self):
		return lx.symbol.fCMD_UNDO | lx.symbol.fCMD_MODEL | lx.symbol.fCMD_REPEAT | lx.symbol.iUNDO_ACTIVE   
 
	def basic_Execute(self, msg, flags):
		lx.out('basic execute')


		undoService = lx.service.Undo()
		if not undoService.State() == lx.symbol.iUNDO_ACTIVE:
		    return

		with mesh.geometry as geo:
			for v in geo.vertices:
				v += (0, 0.5, 0)
				
		mesh.geometry.setMeshEdits()
		mesh.geometry._UNDO_SVC
		
	def cmd_PreExecute(self):
		#execute stuff before basix eceute
		lx.out('pre Execute')
 
lx.bless (MyCommand_Cmd, "my.commandH")

Notifier

  • Notifier Based on the example by Tim Vasquez
import lx
import lxifc
import lxu.command
import random
 
class MyNotifier(lxifc.Notifier):
    masterList = {}
 
    def noti_Name(self):
        return "my.notifier4"
 
    def noti_AddClient(self,event):
        self.masterList[event.__peekobj__()] = event
 
    def noti_RemoveClient(self,event):
        del self.masterList[event.__peekobj__()]
 
    def Notify(self, flags):
        for event in self.masterList:
            evt = lx.object.CommandEvent(self.masterList[event])
            evt.Event(flags)

lx.bless(MyNotifier,"my.notifier4")

class notify_Send(lxu.command.BasicCommand):
 
    def __init__(self):
        lxu.command.BasicCommand.__init__(self)
 
    def basic_Execute(self, msg, flags):
        notifier = MyNotifier()
        notifier.Notify(lx.symbol.fCMDNOTIFY_LABEL)
 
    def basic_Enable(self,msg):
        return True
 
lx.bless(notify_Send, "notify.send4")

class CmdNotifiers(lxu.command.BasicHints):
 
    def __init__(self):
        self._notifiers = [('my.notifier4','')]
 
class notify_Receiver(lxu.command.BasicCommand):
 
    def __init__(self):
        lxu.command.BasicCommand.__init__(self)
 
    def basic_Execute(self, msg, flags):
        pass
 
    def arg_UIValueHints(self, index):
        return CmdNotifiers()    
 
    def basic_ButtonName(self):
        rstr = "Hello: %s" % str(random.randrange(1,10000))
        return "Dog: %s" % rstr
 
    def basic_Enable(self,msg):
        return True
 
lx.bless(notify_Receiver, "notify.recv4")

Check if command Enabled

import modo, lx, lxu
msg = lx.object.Message()
msg = lx.service.Message().Allocate()
msg.SetCode(lx.symbol.iCM_ACT_DONE)
cmd_svc = lx.service.Command() 
cmd = cmd_svc.Spawn(lx.symbol.iCTAG_NULL, 'set.sceneAsDefault')
try:
    test = cmd.Enable(msg)
    lx.out('worked')
except Exception as e:
    dialog = modo.dialogs.alert("Look Here", "Error: %s" % e)
lx.out('We continued on')

Get mesh from meshop

I use this in a tool i made, that checks for mesh, then checks for a defomered mesh,. then if thats off it checks for a morphed mesh etc. Answer to: Is there any way to check a procedural mesh's mesh? I want to check if a mesh, that is getting its geo via a mesh merge, contains some specific data. I am grabbing the mesh via the sICHAN_MESH_MESH channel and using the Edit Action. I just end up getting an empty mesh.

for (unsigned meshIter = 0; meshIter < outCount; meshIter++)
		{
			CLxUser_MeshService msh_srv;
			CLxUser_Locator mesh_locator;
			CLxUser_Mesh morph_mesh, deform_mesh;
			bool bUseDeformedMesh = false;
			scan.BaseMeshByIndex(meshIter, scan_mesh); // get mesh
			msh_srv.ItemFromMesh(scan_mesh, scan_item); // get mesh item
			scan.MeshInstance(meshIter, morph_mesh);
			// We are getting the item position, so that we can compare vert pos in world space, which the lasso falloff seems to need.
			CLxUser_ChannelRead read;
			mesh_locator.set(scan_item);
			scan_item.GetContext(scene);
			if (!scene.test())
			{
				return;
			}
			scene.GetChannels(read, time);
			CLxUser_ItemGraph graph;
			scene.GetGraph(LXsGRAPH_DEFORMERS, graph);
			unsigned int dfrm_count_fwd, dfrm_count_rev = 0;
			graph.FwdCount(scan_item, &dfrm_count_fwd);
			graph.RevCount(scan_item, &dfrm_count_rev);
			if (dfrm_count_fwd > 0 || dfrm_count_rev > 0)
			{
				if (viewevent->type == LXi_VIEWTYPE_3D)
				{
					// Todo: Presumably I can get the view from the viewevent somehow?
					CLxUser_View3DportService srv_vp;
					int idxVP = srv_vp.Current();
					CLxUser_View3D view;
					srv_vp.View(idxVP, view);
					// if we have deformers on, we want the deformer mesh, instead of the edit mesh.
					LxResult deformers = view.Deformers();
					if (deformers == LXe_TRUE)
					{
						// Get deformed version of the mesh. 
						CLxUser_MeshFilter mesh_filter;
						CLxUser_MeshFilterIdent meshIdent_filter;
						read.Object(scan_item, LXsICHAN_MESH_MESH, mesh_filter);
						const char* ident = NULL;
						scan_item.Ident(&ident);
						mesh_filter.GetMesh(deform_mesh);
						if (deform_mesh.test())
						{
							bUseDeformedMesh = true;
							scan_mesh = deform_mesh;
						}
					}
				}
			}
			if (!bUseDeformedMesh)
			{
				// we have no deformers, or they are off, so now we want to see if we have a morph map selected
				LXtID4 morphType = LXi_VMAP_MORPH;
				CLxUser_VMapPacketTranslation vmap_pkt_trans;
				void* pkt;
				vmap_pkt_trans.autoInit();
				unsigned vmapCount = srv_sel.Count(vmapType);
				if (vmapCount > 0)
				{
					for (unsigned vmapIter = 0; vmapIter < vmapCount; vmapIter++)
					{
						pkt = srv_sel.ByIndex(vmapType, vmapIter);
						LXtID4 outVmapType;
						vmap_pkt_trans.Type(pkt, &outVmapType);
						if (outVmapType == morphType)
						{
							if (morph_mesh.test())
							{
								scan_mesh = morph_mesh;
							}
							break;
						}
					}
				}
			}

Raycasting for tools from screen

CLxUser_VectorStack	vector_stack (tool_vector);
if (! vector_stack.test ())
{
    return LXe_FALSE;
}

//
// 1. Using CLxUser_Raycast
//
CLxUser_RaycastPacket raycast_packet {};
if (! vector_stack.ReadObject (raycast_packet_offset_, raycast_packet))
{
    return LXe_FALSE;
}

auto screen_event = static_cast<LXpToolScreenEvent*>(vector_stack.Read (screen_event_packet_offset_));
if (! screen_event)
{
    return LXe_FALSE;
}

LXtHitPolygon hit_polygon {};
raycast_packet.HitPolygon (vector_stack, LXf_LAYER_ACTIVE, screen_event->fcx, screen_event->fcy, &hit_polygon);

//
// 2. Using LXpToolHitEvent
//
auto hit_event = static_cast<LXpToolHitEvent*>(vector_stack.Read (hitevent_packet_offset_));
if (! hit_event)
{
    return LXe_FALSE;
}
if (! hit_event->hit.pol)
{
    return LXe_FALSE;
}

//
// 3. Using CLxUser_View3D and CLxUser_Surface(not shown; must account for item transforms)
//    I don't use modo's macro maths in practice.
//
CLxUser_View3DportService view_service {};
const int view_index_current = view_service.Current ();

CLxUser_View3D view {};
view_service.View (view_index_current, view);
if (! view.test ())
{
    return LXe_FALSE;
}

auto screen_event = static_cast<LXpToolScreenEvent*>(vector_stack.Read (screen_event_packet_offset_));
if (! screen_event)
{
    return LXe_FALSE;
}

const int pos_flags {0}; // alternatives: LXi_VPTO3D_SNAP; LXi_VPTO3D_WORK
LXtVector point_from_screen {};
if (LXx_FAIL (view.To3D (screen_event->fcx, screen_event->fcy, point_from_screen, pos_flags)))
{
    return LXe_FALSE;
}

LXtVector ray_direction {};
const double dist_to_point_from_ray_origin = view.EyeVector (point_from_screen, ray_direction);

LXtVector ray_origin {};
LXx_VCPY  (ray_origin, point_from_screen);
LXx_VADDS (ray_origin, ray_direction, dist_to_point_from_ray_origin * -1.0);

// pass ray to function that uses CLxUser_Surface::RayCast

View3d Item Package drawing 2d shapes to the screen(as unlike tool you dont have access to pixel space)

int width, height;
view.Dimensions(&width, &height);
double xd = width - 25;
double yd = height * 0.5;
int sides = 6;
double radius = 16;
double theta = LXx_TWOPI / sides;
double rad = 0.0;
LXtVector vCen, xyPos;
view.ToModel(xd, yd, vCen, 0);
//Contour pass
draw.BeginW(LXiSTROKE_LINES, COLOR_GREY, 0.8, 2.0);
for (unsigned int sidecount = 0; sidecount < sides; sidecount++)
{
    view.ToModel((xd + cos(rad) * radius), (yd + sin(rad) * radius), xyPos, 0);
    draw.Vert(xyPos, LXiSTROKE_ABSOLUTE);
    rad -= theta;
    view.ToModel((xd + cos(rad) * radius), (yd + sin(rad) * radius), xyPos, 0);
    draw.Vert(xyPos, LXiSTROKE_ABSOLUTE);
}
//Fill pass
draw.BeginPolygons(LXiSTROKE_TRIANGLES, COLOR_BLACK, 0.5, 1.0, 0.0, 0.0, 1, 0);
for (unsigned int sidecount = 0; sidecount < sides; sidecount++)
{
    draw.Vert(vCen, LXiSTROKE_ABSOLUTE);
    view.ToModel((xd + cos(rad) * radius*2), (yd + sin(rad) * radius), xyPos, 0);
    draw.Vert(xyPos, LXiSTROKE_ABSOLUTE);
    rad -= theta;
    view.ToModel((xd + cos(rad) * radius * 2), (yd + sin(rad) * radius), xyPos, 0);
    draw.Vert(xyPos, LXiSTROKE_ABSOLUTE);
}

Config - Minmising Header

<?xml version="1.0"?>
<configuration>
    <atom type="Frame">
        <hash type="Layout" key="edit.decalPresetMaker_Layout" val="applicationLayout">
          <atom type="IdealSize">670 610</atom>
          <list type="Port">customview 0 1 0 1 96738922916:vp</list>
          <atom type="PostRestoreCommand"></atom>
          <atom type="Icon"></atom>
          <atom type="InputRemappingContext"></atom>
          <atom type="Tooltip"></atom>
          <atom type="UserName">dpr.decalPresetMakerLayout</atom>
          <atom type="SwitcherClass">normal</atom>
          <atom type="SwitcherThumbnail"></atom>
        </hash>
        
        <hash type="LayoutWindow" key="dpr.decalPresetMaker_Window">
            <atom type="Title">Decal Preset Maker</atom>
            <atom type="Contents">(layout) decalPresetMaker_Layout</atom>
            <atom type="Size">670 610</atom>
            <atom type="ShowSwitcherBar">false</atom>
        </hash>
        
        
        <hash type="customview" key="edit.96738922916:vp" val="unregistered">
          <atom type="Identifier">55992922917:customview</atom>
          <atom type="Server">dpr.decalPresetMaker</atom>
          <atom type="ViewportLock2">0 0</atom>
          <atom type="MinHeader">1</atom> <!-- This will collapse the top horizontal Title bar -->
          <atom type="QuadLock">0</atom>
          <atom type="ViewportTitle">Decal Preset Maker</atom>
          <atom type="ViewportClass">vpapplication</atom>
        </hash>
    </atom>
</configuration>

Config - Default Value

<?xml version="1.0"?>
<configuration kit="SYZER" version="fourteen.0" and="major=14">
	<atom type="UserValues">
	    <hash type="Definition" key="sceneio.syzer.libraryfolder"><atom type="Type">string</atom><atom type="defaultvalue">Z:\Library</atom></hash>
	    <hash type="RawValue"   key="sceneio.syzer.libraryfolder">Z:\Library</hash>
	</atom>
</configuration>

Tool - Filtering drawing 2d and 3d

LXpToolViewEvent	*viewEvent = (LXpToolViewEvent *)vec.Read(mPacketOffsets[ePacketOffset_ViewEvent]);
    if (viewEvent->type == LXi_VIEWTYPE_3D){ // Draw 3d shapes}
    if (viewEvent->type == LXi_VIEWTYPE_2D){ // Draw 2d shapes}