-- Rockstar mloPortal Object -- Rockstar North -- 14/10/2005 -- by Greg Smith -- -- 12/03/2007 -- DHM -- -- Add multiple portal objects parameter block and associated UI -- Add version update event handler to cope with this change -- Remove "Door/Window Object" rollout -- -- 04/03/2010 -- Luke Openshaw -- Check for rollout initialisation before accessing pick button rollout controls -- or Max 2010 will crash like the piece of shit that it is -- -- -- helper object for milo portal setup plugin helper GtaMloPortal name:"Gta MloPortal" classID:#(0xa697b45, 0x197567c7) category:"Gta" extends:RSGrid version:2 ( local gIsInit = false rollout objRollout "Rooms" ( label lblFirst "First:" offset:[-46,0] pickbutton btnFirst "none" width:100 offset:[18,-20] button btnFirstReset "*" width:10 offset:[74,-26] label lblSecond "Second:" offset:[-55,0] pickbutton btnSecond "none" width:100 offset:[18,-20] button btnSecondReset "*" width:10 offset:[74,-26] button btnFlip "Flip Portal" width:100 --offset:[18,-40] button btnRetard "Am I Retarded?" width:100 --offset:[18,-40] fn CalcPortalVec portalObj = ( portalPt = [ 0.0, 0.0, 5.0 ] portalPt = portalPt * portalObj.transform portalVec = portalPt - portalObj.position portalVec = normalize portalVec return portalVec ) fn RetardationCheck = ( portalObj = selection[1] room1 = portalObj.LinkFirst room2 = portalObj.LinkSecond bbMin = [10000, 10000, 10000] bbMax = [-10000, -10000, -10000] if room1 != undefined then ( for roomObj in room1.children do ( if roomObj.position.x < bbMin.x then bbMin.x = roomObj.position.x if roomObj.position.y < bbMin.y then bbMin.y = roomObj.position.y if roomObj.position.z < bbMin.z then bbMin.z = roomObj.position.z if roomObj.position.x > bbMax.x then bbMax.x = roomObj.position.x if roomObj.position.y > bbMax.y then bbMax.y = roomObj.position.y if roomObj.position.z > bbMax.z then bbMax.z = roomObj.position.z ) centroid = (bbMin + bbMax) / 2 roomVec = portalObj.position - centroid roomVec = normalize roomVec portalVec = CalcPortalVec portalObj if (dot portalVec roomVec) < 0 then return true return false ) if room2 != undefined do ( for roomObj in room2.children do ( if roomObj.position.x < bbMin.x then bbMin.x = roomObj.position.x if roomObj.position.y < bbMin.y then bbMin.y = roomObj.position.y if roomObj.position.z < bbMin.z then bbMin.z = roomObj.position.z if roomObj.position.x > bbMax.x then bbMax.x = roomObj.position.x if roomObj.position.y > bbMax.y then bbMax.y = roomObj.position.y if roomObj.position.z > bbMax.z then bbMax.z = roomObj.position.z ) centroid = (bbMin + bbMax) / 2 roomVec = portalObj.position - centroid roomVec = normalize roomVec portalPt = [ 0.0, 0.0, 5.0 ] portalPt = portalPt * portalObj.transform portalVec = portalPt - portalObj.position portalVec = normalize portalVec if (dot portalVec roomVec) > 0 then return true return false ) --else ( -- messagebox "Portal has no rooms." --) return true ) on objRollout open do ( gIsInit = true if this.LinkFirst != undefined then ( btnFirst.caption = this.LinkFirst.name ) if this.LinkSecond != undefined then ( btnSecond.caption = this.LinkSecond.name ) ) on btnFirstReset pressed do ( sel = selection sel.LinkFirst = undefined ) on btnSecondReset pressed do ( sel = selection sel.LinkSecond = undefined ) on btnFirst picked obj do ( if ((classof(obj) as string) != "GtaMloRoom") then this.LinkFirst = undefined ) on btnSecond picked obj do ( if ((classof(obj) as string) != "GtaMloRoom") then this.LinkSecond = undefined ) on btnFlip pressed do ( portalVec = CalcPortalVec selection[1] if (dot portalVec [0.0,0.0,1.0]) > 0.95 or (dot portalVec [0.0,0.0,1.0]) < -0.95 then ( rotatePortal = eulerangles 180 0 0 rotate selection[1] rotatePortal ) else ( rotatePortal = eulerangles 0 0 180 rotate selection[1] rotatePortal ) ) on btnRetard pressed do ( if RetardationCheck() == true then messagebox "This portal is probably reversed. If it does not behave correctly in game, flip it and re-export." else messagebox "Portal seems OK." ) ) parameters objParams rollout:objRollout ( LinkFirst type:#node ui:btnFirst LinkSecond type:#node ui:btnSecond on LinkFirst set val do ( -- This will crash max in 2010 and is unncessary anyway --if objRollout == undefined then return false if gIsInit == true then ( if val != undefined then ( objRollout.btnFirst.caption = val.name ) else( objRollout.btnFirst.caption = "none" ) ) ) on LinkSecond set val do ( -- This will crash max in 2010 and is unncessary anyway --if objRollout == undefined then return false if gIsInit == true then ( if val != undefined then ( objRollout.btnSecond.caption = val.name ) else ( objRollout.btnSecond.caption = "none" ) ) ) ) -- Unused but maintained for backwards compatibility parameters objParams2 --DHM -- rollout:objRollout2 ( PortalObject type:#node -- DHM -- ui:btnPortalObject on PortalObject set val do ( if objRollout2 == undefined then return false if val != undefined then ( objRollout2.btnPortalObject.caption = val.name ) else( objRollout2.btnPortalObject.caption = "none" ) ) ) -- New interface rollout to allow multiple objects to be attached to Mlo Portal objects -- Added 12/03/2007, dhm rollout objRollout3 "Door/Window Objects" ( listbox lbObjects "Objects:" height:10 align:#left toolTip:"List of objects attached to the Portal" button btnAdd "Add (by Pick)" width:100 toolTip:"Add an object by clicking here and then picking the object to add from a viewport" button btnRemove "Delete" width:100 toolTip:"Select an object in the list and click here to remove the object from the Portal" -- Rollout open event handler on objRollout3 open do ( -- Populate our listbox because of issue with event handler and tab type (see below) if ( undefined != this.PortalObjects ) then ( for nIndex = 1 to this.PortalObjects.count do ( if ( undefined != this.PortalObjects[nIndex] ) then ( lbObjects.items = append lbObjects.items this.PortalObjects[nIndex].name ) ) ) ) -- Add button event handler on btnAdd pressed do ( -- This check is done at run-time (and a variable array is used) so that we -- can support more attached objects in the future (if required) if ( this.PortalObjects.count == 4 ) then ( MessageBox( "Portals can only have upto 4 attached objects. No more objects may be attached to this Portal." ) return 0 ) obj = pickObject "Select object to attach to Portal" sClassName = classof( obj ) as string if ( ( "Editable_mesh" != sClassName ) and ( "XRefObject" != sClassName ) ) then ( MessageBox( "Only Editable Mesh and XRefObjects may be attached to a Portal" ) return 0 ) -- Append to our PortalObjects parameter array only if the object -- isn't already attached if ( 0 == ( findItem this.PortalObjects obj ) ) then ( this.PortalObjects[this.PortalObjects.count+1] = obj ) ) -- Remove button event handler on btnRemove pressed do ( if ( 0 == lbObjects.selection ) then ( MessageBox( "You must select an object to remove from the Portal first." ) return 0 ) if ( this.PortalObjects.count > 0 ) then ( -- Remove from our PortalObjects parameter array this.PortalObjects = deleteItem this.PortalObjects lbObjects.selection -- Hack for when we have zero objects our set handler doesn't get fired -- to update our ListBox if ( 0 == this.PortalObjects.count ) then ( lbObjects.items = #() this.PortalObjects = #() ) ) ) ) parameters objParams3 rollout:objRollout3 ( -- Max doesn't allow us to automatically use a nodeTab against a UI element -- so we have to do it manually in the event handler code above. PortalObjects type:#nodeTab tabSizeVariable:true -- Damn MaxScript: this doesn't get called upon initialisation. -- If it were a regular type it would but since its a "tab" type it doesn't... on PortalObjects set val index do ( if objRollout3 == undefined then return false -- Debug statements --print "PortalObjects Set:" --print PortalObjects -- Refresh our listbox with our current parameters objRollout3.lbObjects.items = #() for nIndex = 1 to this.PortalObjects.count do ( objRollout3.lbObjects.items = append objRollout3.lbObjects.items this.PortalObjects[nIndex].name ) -- Set selection to 0 objRollout3.lbObjects.selection = 0 ) ) -- Our update event handler -- Here we maintain backwards compatibility by moving the single reference in -- objParams2 to the objParams3 array. on update do ( -- Update version 1 instances to version 2 -- by moving the reference in objParams2 to objParams3 and then setting the -- objParams2.PortalObject to undefined if ( version == 1 ) then ( if ( this.PortalObject != undefined ) then ( this.PortalObjects = append this.PortalObjects this.PortalObject this.PortalObject = undefined ) ) ) )