[QUOTE=
what id like to do is make a composite slider object for a morpher that adds min/max buttons in dotnet. but i cant get the trackbar scroll event in the control to be exposed to the base usercontrol scroll event. Any thoughts?
I had some problems exposing properties to Max when I tried defining classes within classes.
In the end I kept everyting very flat and simple.
I did manage to create my own event ( called every time the mouse is moved) from this article
whats your code like could I have a Look?
Hi Ken, thanks for the article – im trying to get my head around this.
I wasnt sure if the vb.net ‘Addhandler’ method actually creates the delegates for you or not.
But I have been having the same problem exposing the properties of nested classes. Someone said you can expose the nested item as a property within the class, but that sounds like the wrong way to go since you could then change it programatically, as it would expose the whole element. you essentially only want to show the bit you want people to see, just like you did with the label control on your code. I tried something inheriting the trackbar class too, as i though it would automatically inherit the scroll handler, but wasnt able to make the trackbar smaller in the UI so that i could add the buttons this way. Im sure there is a correct way of doing it and Im just doing it wrong!
But I think composite dotnet controls (ie a user control build from other dotnet Ui controls) would be useful for character animation – a composite morph slider would give you a plug in control that you could set up to each target, without having to build a UI for reset button and you could have programmable presets too for common values if you wanted.
I cant get access to my code as i’m at work, but i’ll try to post something later. Like you said Ken, i’m not sure my programming skills are that pretty! thanks mate.
It took me a while to get my head round events and deligates.
I'll try and explain how it works in my code.
Basically there are two events working here. The MouseMove event which notifies .setPos which in turn notifies Max using a 'posEvent'. I did this because I wanted to be sure that the target position had been updated before Max registered the event.
This code is outside the usercontrol object.
The delegate which subscribers must implement
public delegate void PosEventHandler(object sender,PosEventArgs e);
A simple class that inherits from eventArgs to hold the mouse postion.
An instance of this class will be sent to subscribers every time the event is triggered
public class PosEventArgs : EventArgs
{
public float x = 0;
public float y = 0;
public int index = 0;
public PosEventArgs(FloatPoint p,int i)
{
x = p.x;
y = p.y;
index = i;
}
}
The Rest of the code is inside the usercontrol class
The event controls access to the delegate
public event PosEventHandler PosEvent;
This function Returns a PosEventArgs instance.
which contains the mouse position ‘this.pos’, and an index
Note… the index isn’t used at the moment which is why its set to ‘1’ …
… it’s there so I can expand the code later…
public PosEventArgs GetPosEventArgs()
{
return new PosEventArgs(this.pos,1);
}
If anyone has subscribed notify them
protected virtual void OnPosEvent(PosEventArgs e)
{
if (PosEvent != null) PosEvent(this, e);
}
This is the function called by the mouse move event…
After moving the Target object by calling ‘MoveCross()’ it then calls ‘OnPosEvent’ which notifies the subscribers
private void setPos(object sender, System.Windows.Forms.MouseEventArgs e)
{
if ((e.Button == MouseButtons.Left) && !mouseCancel)
{
MoveCross();
OnPosEvent(GetPosEventArgs());
}
}
This is the code generated by visual studio which adds my function 'setPos' to the list of functions called when the mouse is moved.
this.Target.MouseMove += new System.Windows.Forms.MouseEventHandler(this.setPos);
Unfortunitly I’m in production in Max 8 right now so I think I’m going to be stuck with the bitmap method. Here is my problem. I’m want to use the control in a CA def on a modifier. To set the position I need to get the screenPos of the mouse- the position of the dialog – the position of the imgTag. For a dialog getDialogPos will do that but for a rollout it will not. Even the rollout.pos property doesn’t work as it is not in a rollout floater. Any one have any idea of how I can nail down the position of the mouse over an image tag that is in the modifier panel?
Ken –
Many thanks for the heads up. I had actually got a tutorial in a book about this pertaining to a treeview, it hadn’t occured to me to use it with other controls and i was barking up a different alley. I will post some code tonight.
paul –
This isnt much help except to say I tried to do the same thing as you a while back and came up with the same conclusion. I made a max8 control similar to yours (although not as trippy!) for eyeball position on a character. I couldnt figure out why it wasnt working, except for the fact that inside the modifer panel it seems to override the mousedown events to provide the ability to scroll the panel up and down. it doesnt do this on buttons, but seems to disable the handlers for bitmaps. How have you got round the lack of a mousemove handler in imgtag? In the end, I used a checkbox linked to an ini setting that remembered whether I wanted the dialog to open the rollout floater on the selection of the node. This was tied to a selectionset callback that destroyed it when the character node with the ca’s was deselected. this was the best i could come up with.
Pete, Im’ not having any issues with the event handlers for the imgTag, my problem is know where the mouse is in relation to the imgTag. How did you work that out.
Here is a version of what I’m thinking of using, not so trippy. This one is in a createDialog and I can get the position of the mouse – position of dialog – position of imgTag. When you do this in the modifier panel I can’t get the position of the rollout on screen, only the position of the mouse and the imgTag, this isn’t enough to solve where the mouse is over the imgTag.
rollout testImgTag "Test Img Tag" width:220
(
local curBoxControl=undefined
local curSliderControlX=undefined
local curSliderControlY=undefined
local boxControlItVal=[0,0]
local crossCol=(color 255 0 0)
local circleCol=(color 0 0 100)
local bgCol=(color 100 100 100)
local gridCol=(color 120 120 120)
local gridSpace=25
imgTag boxControlIt "MouseTracker" \
height:100 width:100 bitMap:undefined
timer mouseTime interval:1
fn boxControl control:undefined width:0 height:0 pos:[0,0]=
(
if control!=undefined then
(
local bm=bitmap width height color:bgCol
for h = 0 to height by gridSpace do
(
for i = 0 to width do (setPixels bm [i,h] #(gridCol))
)
for w = 0 to width by gridSpace do
(
for i = 0 to height do (setPixels bm [w,i] #(gridCol))
)
for i = 0 to width do (setPixels bm [i,pos.y] #(crossCol))
for i = 0 to height do (setPixels bm [pos.x,i] #(crossCol))
r=10
j=pos.x
k=pos.y
for i = 1 to 360 by 5 do
(
x=r*cos i + j
y=r*sin i + k
setPixels bm [x,y] #(circleCol)
)
control.bitmap=bm
boxControlItVal=pos
)
)
local rcMenuCon=undefined
fn conMenus con:undefined=
(
rcMenu menu
(
menuItem reset "Reset"
menuItem resetX "Reset X"
menuItem resetY "Reset Y"
on reset picked do
(
boxControlItVal=[rcMenuCon.width/2,rcMenuCon.height/2]
boxControl control:rcMenuCon width:rcMenuCon.width height:rcMenuCon.height pos:boxControlItVal
)
on resetX picked do
(
boxControlItVal=[boxControlIt.width/2,boxControlItVal.y]
boxControl control:rcMenuCon width:rcMenuCon.width height:rcMenuCon.height pos:boxControlItVal
)
on resetY picked do
(
boxControlItVal=[boxControlItVal.x,rcMenuCon.height/2]
boxControl control:rcMenuCon width:rcMenuCon.width height:rcMenuCon.height pos:boxControlItVal
)
)
rcMenuCon=con
menu
)
local testMouseOut=false
on boxControlIt lbuttondown pos flag do
(
testMouseOut=true
curBoxControl=boxControlIt
circleCol=(color 200 0 0)
)
on boxControlIt lbuttonup pos flag do
(
print "mouseUp"
testMouseOut=false
circleCol=(color 0 0 100)
dPos=mouse.screenPos-(GetDialogPos testImgTag)-[3,22]
newPos=dPos-boxControlIt.pos
boxControl control:boxControlIt width:boxControlIt.width height:boxControlIt.height pos:newPos
curBoxControl=undefined
gc light:true
)
on boxControlIt mouseout do
(
if testMouseOut then
(
circleCol=(color 0 0 100)
dPos=mouse.screenPos-(GetDialogPos testImgTag)-[3,22]
newPos=dPos-boxControlIt.pos
boxControl control:boxControlIt width:boxControlIt.width height:boxControlIt.height pos:newPos
)
curBoxControl=undefined
gc light:true
)
on boxControlIt rbuttonDown do
(
PopupMenu (conMenus con:boxControlIt)
)
on mouseTime tick do
(
dPos=mouse.screenPos-(GetDialogPos testImgTag)-[3,22]
if curBoxControl!=undefined then
(
newPos=dPos-curBoxControl.pos
boxControl control:curBoxControl width:curBoxControl.width height:curBoxControl.height pos:newPos
)
)
on testImgTag open do
(
boxControl control:boxControlIt width:boxControlIt.width height:boxControlIt.height pos:[boxControlIt.width/2,boxControlIt.height/2]
)
)
createDialog testImgTag
Paul, one thing I figured out while working on my “Box Drawing” script was that IMGTags flicker, but bitmaps don’t.
Perhaps what you should do is take in all of the mouse controls through a transparent IMGTAG which doesn’t change and then modify a BITMAP below that.
Hi Paul,
I used a much simpler setup as you, but i used the mousemove property on the rollout to return the position and set the dialog background to the bitmap. Although it simplifies things, it is not better, as I couldn’t get the mouse.state global to work over the rollout (i think you said in a previous post it only works in a viewport) So my version was to trigger it on a keyboard.controlpressed event. This didnt matter, as as soon as you put this rollout in an attribute and assign it to the modify/command panel, it no longer registers the mouse move event. Since i couldnt figure a better way of doing this until your example i was looking into writing a dotnet one. (which Ken has done brilliantly) but in the end, whatever i did is rendered non functioning when placed in an attribute inside the panel. which was why i decided to create the rollout from the character attribute opening and destroy it when the object was deselected. mooo :shrug:
i used your code as a base as i liked your setpixel method.
rollout testImgTag "Test Img Tag" width:100 height:100
(
fn boxControl control:undefined width:0 height:0 pos:[0,0]=
(
if control!=undefined then
(
local curBoxControl=undefined
local curSliderControlX=undefined
local curSliderControlY=undefined
local boxControlItVal=[0,0]
local crossCol=(color 255 0 0)
local circleCol=(color 0 0 100)
local bgCol=(color 100 100 100)
local gridCol=(color 120 120 120)
local gridSpace=25
local bm=bitmap width height color:bgCol
for h = 0 to height by gridSpace do
(
for i = 0 to width do (setPixels bm [i,h] #(gridCol))
)
for w = 0 to width by gridSpace do
(
for i = 0 to height do (setPixels bm [w,i] #(gridCol))
)
for i = 0 to width do (setPixels bm [i,pos.y] #(crossCol))
for i = 0 to height do (setPixels bm [pos.x,i] #(crossCol))
r=10
j=pos.x
k=pos.y
for i = 1 to 360 by 5 do
(
x=r*cos i + j
y=r*sin i + k
setPixels bm [x,y] #(circleCol)
)
SetDialogBitmap testImgTag bm
testImgTagVal=pos
)
)
on testImgTag mousemove pos do
(
if keyboard.controlpressed do
(
format "Mouse Position : %
" pos
curBoxControl=testImgTag
circleCol=(color 200 0 0)
boxControl control:curBoxControl width:curBoxControl.width height:curBoxControl.height pos:Pos
)
)
on testImgTag open do
(
boxControl control:testImgTag width:testImgTag.width height:testImgTag.height pos:[testImgTag.width/2,testImgTag.height/2]
)
)
createdialog testimgTag
anyone know how to get a mousestate into this???
am going away but wanted to update with the progress on a morph slider control – will post it when i get back and can finish it off. it has a node string property so that each slider can affect various objects. this is not a great implementation between dotnet and max, but can be coded into any rollout and is good for specific scenarios. It also has a setkey event too that can be assigned to any max function, as well as all the button states to nudge+1,+5+10 and reset all within the control. I am looking on how to implement a callback to update them.
should mention that it wont be limited to just morph targets, by default the range will be 0-100 but i will add a property to change it to whatever you are doing. Im hoping it will be a fast way of adding functionality via a control without having to code each button.
I was excited to see max 2008 new node event system – it looks very promising for many things, not just dotnet control integration. anyone else used this?
will post more next week!
Wow I haven’t seen Swami’s name hanging around a max forum in a very long time. Wonder what ever happened to him. Last I knew he was getting in to photography.
I’ll poke at using bitmaps to day as well but I think that I’m going to end up with the same problems.