-- -- File:: rockstar/helpers/parentiser.ms -- Description:: TXD Parentiser -- -- Author:: Greg Smith -- Date:: 1 March 2007 -- ----------------------------------------------------------------------------- -- Uses ----------------------------------------------------------------------------- filein "pipeline/util/file.ms" ----------------------------------------------------------------------------- -- Global Data ----------------------------------------------------------------------------- RsParentiseTexList = #() RsParentiseRemovedTexList = #() --RsParentiseUsedOnceTexList = #() RsEditing = "" RsCurrentTxdIndex = 0 RsDropItem = undefined RsDragItem = undefined RsMouseDownX = undefined RsMouseDownY = undefined RsParentFileList = #() RsKeyPrepend = "Child" RsSourceFolder = RsMakeSafeSlashes( RsConfigGetContentDir() + "txdparents\\" ) struct RsParentItem (name, parentname, type, textures, depth) ----------------------------------------------------------------------------- -- Functions ----------------------------------------------------------------------------- fn RsPrintDebugInfoAboutDotNetObject obj = ( clearListener() format "Properties:\n" showProperties obj format "\nMethods:\n" showMethods obj format "\nEvents:\n" showEvents obj ) fn RsParentiseReadDataFile datafilename datalist = ( datafile = openfile datafilename mode:"r" if datafile != undefined then ( readState = #none while eof datafile == false do ( datafileline = readline datafile if readState == #none then ( if datafileline == "txd" then ( readState = #txd ) ) else if readState == #txd then ( datatokens = filterstring datafileline "= " txdname = RsLowerCase(datatokens[2]) datafileline = readline datafile datatokens = filterstring datafileline "= " txdparent = RsLowerCase(datatokens[2]) datafileline = readline datafile datatokens = filterstring datafileline "= " txdtype = datatokens[2] as integer loadType = undefined case(txdtype) of ( 1: loadType = 2 2: loadType = undefined 3: loadType = 4 4: loadType = 5 5: loadType = undefined ) txdtextures = #() if loadType != 5 then ( datafileline = readline datafile datatokens = filterstring datafileline "= " txdnumtextures = datatokens[2] as integer if txdnumtextures > 0 then ( for i = 1 to txdnumtextures do ( datafileline = readline datafile datatokens = filterstring datafileline "= " txdtexture = datatokens[2] append txdtextures txdtexture ) ) ) if loadType != undefined then ( append datalist (RsParentItem txdname txdparent loadType txdtextures) ) readState = #none ) ) close datafile ) else ( append datalist (RsParentItem "root" "none" 2 #()) ) datalist ) fn RsLoadParentFileList mapName = ( if mapName == "global" then ( sourceFile = RsSourceFolder + "global.txt" RsParentFileList = #() RsParentiseReadDataFile sourceFile RsParentFileList ) else ( sourceFile = RsSourceFolder + "global.txt" RsParentFileList = #() RsParentiseReadDataFile sourceFile RsParentFileList for item in RsParentFileList do ( if item.type == 4 then item.type = 3 ) sourceFile = RsSourceFolder + mapName + ".txt" loadList = #() RsParentiseReadDataFile sourceFile loadList for item in loadList do ( if item.name == "root" then continue alreadyExists = false for itemSet in RsParentFileList do ( if item.name == itemSet.name then ( alreadyExists = true exit ) ) if alreadyExists == true then continue append RsParentFileList item ) ) ) fn RsGetFileTxdList outputList = ( for item in RsParentFileList do ( if item.type == 4 then ( append outputList item.name ) ) ) fn RsGetTxdParent txdname = ( txdname = RsLowerCase txdname idxObject = 0 for i = 1 to RsParentFileList.count do ( if RsParentFileList[i].name == txdname then ( idxObject = i exit ) ) if idxObject == 0 then return "" RsParentFileList[idxObject].parentname ) -------------------------------------------------------- -- Returns the list of textures belonging to the passed -- in txds parent txd. -------------------------------------------------------- fn RsGetTxdParentTextureList txdname texturelist = ( txdname = RsLowerCase txdname idxObject = 0 -- Get object index from name for i = 1 to RsParentFileList.count do ( if RsParentFileList[i].name == txdname then ( idxObject = i exit ) ) if idxObject == 0 then return 0 while true do ( idxParent = 0 parentname = RsParentFileList[idxObject].parentname if parentname == "root" then return 0 -- Now get the parent txd index from the parent name for i = 1 to RsParentFileList.count do ( if RsParentFileList[i].name == parentname then ( idxParent = i exit ) ) if idxParent == 0 then return 0 -- For each texture the parent txd has in it's list -- append it to the texture list passed in where it -- doesn't already exist for tex in RsParentFileList[idxParent].textures do ( if finditem texturelist tex == 0 then ( append texturelist tex ) ) idxObject = idxParent ) idxObject ) fn RsGetFileTxdTextures txdname texturelist = ( txdname = RsLowerCase txdname removetexlist = #() RsGetTxdParentTextureList txdname removetexlist idxObject = 0 for i = 1 to RsParentFileList.count do ( if RsParentFileList[i].name == txdname then ( idxObject = i exit ) ) if idxObject == 0 then return 0 for tex in RsParentFileList[idxObject].textures do ( if finditem removetexlist tex == 0 then ( append texturelist tex ) ) ) -- -- name: RsMapExportIDEAppendParentTXD -- desc: Append the txdp section to a specified IDE file -- -- This function assumes that the parent texture dictionary list has already -- been populated (see parentiser.ms and the RsParentFileList array). -- -- param: ide_filename - IDE filename to append the txdp section to. -- fn RsMapExportIDEAppendParentTXD ide_filename = ( local writefile = openfile ide_filename mode:"a" if ( undefined != writefile ) then ( format "txdp\n" to:writefile for item in RsParentFileList do ( if (item.type == 4 or item.type == 5) and item.parentname != "root" then ( format "%,%\n" item.name item.parentname to:writefile ) ) format "end\n" to:writefile close writefile ) ) -- -- name: RsTxdParentiserRoll -- -- rollout RsTxdParentiserRoll "Parentiser" width:260 ( --------------------------------------------------------------------------- -- UI --------------------------------------------------------------------------- dotNetControl tv "TreeView" width: 200 height:780 align:#left listbox lstTex "Textures" offset:[225,-780] width:240 height:20 listbox lstRemoved "Textures In Parents" offset:[225,0] width:240 height:20 --------------------------------------------------------------------------- -- Functions --------------------------------------------------------------------------- fn getListIdFromTreeNode treeNode = ( if treeNode.text == "root" then return 1 srcTextA = treeNode.Tag.value if srcTextA == "" then ( for i = 1 to RsParentFileList.count do ( item = RsParentFileList[i] if item.name == treeNode.text then return i ) ) else ( srcText = (filterstring srcTextA ":")[2] return (srcText as integer) ) print ("error looking up " + treeNode.text) return 0 ) fn getListIdFromTreeNodeName treeNodeName = ( for i = 1 to RsParentFileList.count do ( if RsParentFileList[i].name == treeNodeName then ( return i ) ) 0 ) fn getParentTextureList theNode texoutList = ( if theNode == undefined then return 0 theParentNode = theNode.Parent if theParentNode != undefined and theParentNode.text != "root" then ( idxTxdItem = getListIdFromTreeNode theParentNode for tex in RsParentFileList[idxTxdItem].textures do ( append texoutList tex ) getParentTextureList theParentNode texoutList ) ) fn updateTexLists theNode = ( RsParentiseTexList = #() RsRawParentiseTexList = #() --RsParentiseUsedOnceTexList = #() RsParentiseRemovedTexList = #() RsParentTexList = #() RsCurrentTxdIndex = 0 if theNode != undefined and theNode.text != "root" then ( idxTxdItem = getListIdFromTreeNode theNode RsCurrentTxdIndex = idxTxdItem getParentTextureList theNode RsParentTexList if theNode.ImageIndex == 2 or theNode.ImageIndex == 3 then ( for tex in RsParentFileList[idxTxdItem].textures do ( append RsRawParentiseTexList tex ) ) else ( texmaplist = #() maxsizelist = #() isbumplist = #() usagelist = #() txdname inputobjlist = #() RsGetInputObjectList rootnode.children inputobjlist RsGetTexMapsByTxdName texmaplist maxsizelist isbumplist usagelist theNode.text srcobjlist:inputobjlist for i = 1 to texmaplist.count do ( texmap = texmaplist[i] usage = usagelist[i] append RsRawParentiseTexList texmap ) ) for tex in RsRawParentiseTexList do ( if tex != undefined and tex != "" then ( if finditem RsParentTexList tex == 0 then ( append RsParentiseTexList tex ) else ( append RsParentiseRemovedTexList tex ) ) ) ) lstTex.items = RsParentiseTexList --lstOnce.items = RsParentiseUsedOnceTexList lstRemoved.items = RsParentiseRemovedTexList ) fn addTxd = ( txdname = RsLowerCase(RsQueryBox "new txd name") if txdname == undefined or txdname == "root" then return 0 append RsParentFileList (RsParentItem txdname "root" 4 #()) keyval = RsKeyPrepend + ":" + (RsParentFileList.count as string) tvnNew = tv.Nodes.Item[0].Nodes.Add txdname tvnNew.tag = dotNetMXSValue keyval tvnNew.ImageIndex = 3 tvnNew.SelectedImageIndex = 3 -- RsPrintDebugInfoAboutDotNetObject tvnNew ) fn renameTxd = ( selItem = tv.SelectedNode if selItem == undefined then return 0 idxTxdItem = getListIdFromTreeNode selItem if RsParentFileList[idxTxdItem].type != 4 then return 0 txdname = RsLowerCase(RsQueryBox "edit txd name" edittext:selItem.text) if txdname != "" then ( selItem.Text = txdname RsParentFileList[idxTxdItem].name = txdname ) ) fn removeTxd = ( selItem = tv.SelectedNode if selItem == undefined or selItem.Text == "root" then return 0 idxTxdItem = getListIdFromTreeNode selItem if RsParentFileList[idxTxdItem].type != 4 then return 0 if querybox "are you sure?" then ( while selItem.Nodes.Count > 0 do ( childNode = selItem.Nodes.Item[0] selItem.Nodes.Remove childNode selItem.Parent.Nodes.Add childNode ) /* ActiveX version tv.Nodes.Remove selItem.Index */ tv.Nodes.Remove selItem deleteitem RsParentFileList idxTxdItem updateTexLists undefined ) ) fn addTexture = ( selItem = tv.SelectedNode if selItem == undefined then return 0 idxFound = getListIdFromTreeNode selItem if RsParentFileList[idxFound].type != 4 then return 0 texname = RsLowerCase(RsQueryBox "new texture name") if finditem RsParentFileList[idxFound].textures texname == 0 then ( append RsParentFileList[idxFound].textures texname ) updateTexLists selItem ) fn renameTexture = ( selItem = tv.SelectedNode if lstTex.selection == 0 or RsCurrentTxdIndex == 0 then return 0 if RsParentFileList[RsCurrentTxdIndex].type != 4 then return 0 idxFound = finditem RsParentFileList[RsCurrentTxdIndex].textures lstTex.selected if idxFound == 0 then return 0 idxSelection = lstTex.selection txdname = RsLowerCase(RsQueryBox "edit txd name" edittext:lstTex.selected) if txdname != "" then ( -- lstTex.items[idxSelection] = txdname RsParentFileList[RsCurrentTxdIndex].textures[idxFound] = txdname updateTexLists selItem ) ) fn removeTexture = ( selItem = tv.SelectedNode if lstTex.selection == 0 or RsCurrentTxdIndex == 0 then return 0 if RsParentFileList[RsCurrentTxdIndex].type != 4 then return 0 idxFound = finditem RsParentFileList[RsCurrentTxdIndex].textures lstTex.selected if idxFound == 0 then return 0 idxSelection = lstTex.selection if querybox "are you sure?" then ( -- deleteitem lstTex.items idxSelection deleteitem RsParentFileList[RsCurrentTxdIndex].textures idxFound updateTexLists selItem ) ) fn getIconFromBitmap thePath number = ( tempBmp = openBitmap thePath iconBmp = bitmap 16 15 for v = 0 to 14 do setPixels iconBmp [0,v] (getPixels tempBmp [(number-1)*16, v] 16) iconBmp.filename = getDir #image +"/_temp.bmp" save iconBmp close iconBmp close tempBmp getDir #image +"/_temp.bmp" ) fn writeDataFile datafilename = ( print "Writing data file..." print RsParentFileList datafile = openfile datafilename mode:"w+" if datafile != undefined then ( for item in RsParentFileList do ( saveType = undefined case(item.type) of ( 1: saveType = undefined 2: saveType = 1 3: saveType = undefined 4: saveType = 3 5: saveType = 4 ) if saveType != undefined then ( if saveType == 4 and item.parentname == "root" then continue format "txd\n" to:datafile format "name = %\n" item.name to:datafile format "parent = %\n" item.parentname to:datafile format "type = %\n" saveType to:datafile if saveType != 4 then ( format "textures = %\n" item.textures.count to:datafile for tex in item.textures do ( format "texture = %\n" tex to:datafile ) ) ) ) close datafile ) ) fn sortParentTxds itema itemb = ( (itema.depth - itemb.depth) ) fn FindNodeWithName strName obRootNode = ( -- RsPrintDebugInfoAboutDotNetObject obRootNode.Text if (obRootNode.Text == strName) then return obRootNode for i = 0 to (obRootNode.Nodes.count - 1) do ( obPossible = FindNodeWithName strName obRootNode.Nodes.Item[i] if (obPossible != undefined) then return obPossible ) return undefined ) fn addTreeData = ( RsLoadParentFileList RsEditing nameList = #() for j = 1 to RsParentFileList.count do ( RsParentFileList[j].depth = 0 append nameList RsParentFileList[j].name ) for j = 1 to RsParentFileList.count do ( testName = RsParentFileList[j].parentname do ( RsParentFileList[j].depth = RsParentFileList[j].depth + 1 idxFound = finditem nameList testName if idxFound == 0 then ( testName = "none" ) else ( testName = RsParentFileList[idxFound].parentname ) ) while (testName != "none") ) qsort RsParentFileList sortParentTxds tvnRoot = tv.Nodes.Add "root" -- tvnNew.tag = dotNetMXSValue keyval tvnRoot.ImageIndex = 1 tvnRoot.SelectedImageIndex = 1 -- RsPrintDebugInfoAboutDotNetObject tvnRoot -- get txd list for scene txdlist = #() txdobjlist = #() if RsEditing != "global" then ( RsGetTxdList rootnode.children txdlist txdobjlist ) for j = 1 to RsParentFileList.count do ( txdItem = RsParentFileList[j] if txdItem.name != "root" then ( idxFound = finditem txdlist txdItem.name if idxFound != 0 then deleteitem txdlist idxFound paritem = FindNodeWithName txdItem.parentname tv.Nodes.Item[0] if paritem != undefined then ( keyval = RsKeyPrepend + ":" + (j as string) if idxFound != 0 then txdItem.type = 5 /* ActiveX version tv.Nodes.Add paritem.index 4 keyval txdItem.name txdItem.type */ tvnNew = paritem.Nodes.Add txdItem.name tvnNew.tag = dotNetMXSValue keyval tvnNew.ImageIndex = (txdItem.type - 1) tvnNew.SelectedImageIndex = (txdItem.type - 1) -- RsPrintDebugInfoAboutDotNetObject tvnNew ) ) ) if RsEditing != "global" then ( for txdname in txdlist do ( append RsParentFileList (RsParentItem txdname "root" 5 #()) keyval = RsKeyPrepend + ":" + (RsParentFileList.count as string) /* ActiveX version tv.Nodes.Add tvnRoot.index 4 keyval txdname 5 */ tvnNew = tvnRoot.Nodes.Add txdname tvnNew.tag = dotNetMXSValue keyval tvnNew.ImageIndex = 4 tvnNew.SelectedImageIndex = 4 -- RsPrintDebugInfoAboutDotNetObject tvnNew ) ) ) -- Determine whether one node is a parent -- or ancestor of a second node. fn ContainsNode node1 node2 = ( -- Check the parent node of the second node. if (node2.Parent == null) then return false; if (node2.Parent.Equals(node1)) then return true; -- If the parent node is not null or equal to the first node, -- call the ContainsNode method recursively using the parent of -- the second node. return ContainsNode node1 node2.Parent ) --//////////////////////////////////////////////////////////// -- events --//////////////////////////////////////////////////////////// /* ActiveX version on tv NodeClick theNode do ( updateTexLists theNode ) */ on tv NodeMouseClick args do ( updateTexLists args.Node ) /* ActiveX version on tv MouseDown Button Shift x y do ( RsMouseDownX = x RsMouseDownY = y ) on tv OLEStartDrag Data AllowedEffects do ( RsDropItem = undefined RsDragItem = tv.HitTest (RsMouseDownX * 15) (RsMouseDownY * 15) if RsDragItem.text == "root" then RsDragItem = undefined if RsDragItem != undefined then ( RsDragItem.CreateDragImage() ) ) on tv OLEGiveFeedback Effect DefaultCursors do ( if RsDragItem == undefined then return 0 local p = getCursorPos tv overitem = tv.hitTest (p.x*15) (p.y*15) if overitem != undefined and overitem.text != RsDragItem.text then ( tv.MousePointer = #ccDefault DefaultCursors = 1 ) else ( tv.MousePointer = #ccNoDrop DefaultCursors = 0 ) ) on tv OLEDragOver Data Effect Button Shift x y State do ( if RsDragItem == undefined then return 0 local p = getCursorPos tv overitem = tv.hitTest (p.x*15) (p.y*15) if overitem != undefined then overitem.Selected = true TVM_GETNEXTITEM = 4352 + 10 TVM_ENSUREVISIBLE = 4352 + 20 TVGN_CARET = 9 TVGN_NEXTVISIBLE = 6 TVGN_PREVIOUSVISIBLE = 7 retval = Windows.SendMessage tv.hWnd TVM_GETNEXTITEM TVGN_CARET 0 nextVis = Windows.SendMessage tv.hWnd TVM_GETNEXTITEM TVGN_NEXTVISIBLE retval prevVis = Windows.SendMessage tv.hWnd TVM_GETNEXTITEM TVGN_PREVIOUSVISIBLE retval if nextVis != undefined then Windows.SendMessage tv.hWnd TVM_ENSUREVISIBLE 0 nextVis if prevVis != undefined then Windows.SendMessage tv.hWnd TVM_ENSUREVISIBLE 0 prevVis if overitem != undefined and overitem.text != RsDragItem.text then ( RsDropItem = overitem Effect = DROPEFFECT_MOVE ) else ( Effect = DROPEFFECT_NONE ) ) on tv OLECompleteDrag Effect do ( if RsDragItem == undefined or RsDropItem == undefined then return 0 tv.MousePointer = #ccDefault idxTxdItem = getListIdFromTreeNode RsDragItem idxTxdDropItem = getListIdFromTreeNode RsDropItem if RsParentFileList[idxTxdItem].type == 3 then return 0 if RsParentFileList[idxTxdDropItem].type == 5 then return 0 RsParentFileList[idxTxdItem].parentname = RsDropItem.text RsDragItem.Parent = RsDropItem RsDragItem = undefined RsDropItem = undefined ) */ on tv ItemDrag args do ( MouseButtonsClass = dotNetClass "System.Windows.Forms.MouseButtons"; DragDropEffectsClass = dotNetClass "System.Windows.Forms.DragDropEffects"; -- Move the dragged node when the left mouse button is used. if (args.Button == MouseButtonsClass.Left) then ( tv.DoDragDrop args.Item DragDropEffectsClass.Move ) ) -- Set the target drop effect to the effect -- specified in the ItemDrag event handler. on tv DragEnter args do ( args.Effect = args.AllowedEffect; ) -- Select the node under the mouse pointer to indicate the -- expected drop location. on tv DragOver args do ( -- Retrieve the client coordinates of the mouse position. clickedPoint = dotNetObject "System.Drawing.Point" args.X args.Y targetPoint = tv.PointToClient clickedPoint targetNode = tv.GetNodeAt targetPoint -- Not over a node DragDropEffectsClass = dotNetClass "System.Windows.Forms.DragDropEffects"; if (targetNode == undefined) then ( args.Effect = DragDropEffectsClass.None return 0 ) -- Select the node at the mouse position. tv.SelectedNode = targetNode RsDropItem = targetNode -- If not allowed, sho with icon if(targetNode.ImageIndex == 4 or targetNode.ImageIndex == 4) then ( -- Make mouse pointer say no args.Effect = DragDropEffectsClass.None; ) else ( -- Make mouse pointer happy args.Effect = DragDropEffectsClass.Move; ) ) on tv DragDrop args do ( -- Retrieve the client coordinates of the drop location. clickedPoint = dotNetObject "System.Drawing.Point" args.X args.Y targetPoint = tv.PointToClient clickedPoint -- Retrieve the node at the drop location. targetNode = tv.GetNodeAt targetPoint -- Retrieve the node that was dragged. -- draggedNode = (TreeNode)args.Data.GetData(typeof(TreeNode)); -- draggedNode = dotNetObject "System.Windows.Forms.TreeNode" TreeNodeClass = dotNetClass "System.Windows.Forms.TreeNode" draggedNode = args.Data.GetData(TreeNodeClass); RsDragItem = draggedNode -- RsPrintDebugInfoAboutDotNetObject draggedNode -- Confirm that the node at the drop location is not -- the dragged node or a descendant of the dragged node. DragDropEffectsClass = dotNetClass "System.Windows.Forms.DragDropEffects"; bDraggedAndTargetNodesTheSame = draggedNode.Equals targetNode bDraggedNodeContainsTargetNode = ContainsNode draggedNode targetNode if ( (not bDraggedAndTargetNodesTheSame) and (not bDraggedNodeContainsTargetNode) ) then ( -- If it is a move operation, remove the node from its current -- location and add it to the node at the drop location. if (args.Effect == DragDropEffectsClass.Move) then ( draggedNode.Remove(); targetNode.Nodes.Add(draggedNode); ) -- Expand the node at the location -- to show the dropped node. targetNode.Expand(); ) -- Parentising logic if RsDragItem == undefined or RsDropItem == undefined then return 0 idxTxdItem = getListIdFromTreeNode RsDragItem idxTxdDropItem = getListIdFromTreeNode RsDropItem if RsParentFileList[idxTxdItem].type == 3 then return 0 if RsParentFileList[idxTxdDropItem].type == 5 then return 0 RsParentFileList[idxTxdItem].parentname = RsDropItem.text RsDragItem = undefined RsDropItem = undefined ) on RsTxdParentiserRoll open do ( if RsEditing == "" then ( DestroyDialog RsTxdParentiserRoll return 0 ) -- initialise the treeview iconDir = (getdir #scripts) + "\\rockstar\\data\\" myImageList = dotNetObject "ImageList"; ImageClass = dotNetClass "System.Drawing.Image"; myImageList.Images.Add(ImageClass.FromFile(iconDir + "\\parentise_1.bmp")); myImageList.Images.Add(ImageClass.FromFile(iconDir + "\\parentise_2.bmp")); myImageList.Images.Add(ImageClass.FromFile(iconDir + "\\parentise_3.bmp")); myImageList.Images.Add(ImageClass.FromFile(iconDir + "\\parentise_4.bmp")); myImageList.Images.Add(ImageClass.FromFile(iconDir + "\\parentise_5.bmp")); -- Assign the ImageList to the TreeView. tv.ImageList = myImageList; tv.AllowDrop = true tv.HotTracking = true addTreeData() -- RsPrintDebugInfoAboutDotNetObject tv ) on RsTxdParentiserRoll close do ( if querybox "save data?" then ( if RsEditing == "global" then ( writeDataFile (RsSourceFolder + "global.txt") ) else ( writeDataFile (RsSourceFolder + RsEditing + ".txt") ) ) ) ) rcmenu ParentiseRCmenu ( subMenu "TXD" ( menuItem txd_add "Add" menuItem txd_rename "Rename" menuItem txd_remove "Remove" ) subMenu "Texture" ( menuItem texture_add "Add" menuItem texture_rename "Rename" menuItem texture_remove "Remove" ) on txd_add picked do (RsTxdParentiserRoll.addTxd()) on txd_rename picked do (RsTxdParentiserRoll.renameTxd()) on txd_remove picked do (RsTxdParentiserRoll.removeTxd()) on texture_add picked do (RsTxdParentiserRoll.addTexture()) on texture_rename picked do (RsTxdParentiserRoll.renameTexture()) on texture_remove picked do (RsTxdParentiserRoll.removeTexture()) ) fn RsCreateParentiserDialog setmapName = ( format "Parentiser: %\n" setmapName RsEditing = setmapName CreateDialog RsTxdParentiserRoll modal:false width:500 height:800 menu:ParentiseRCmenu ) -- rockstar/helpers/parentiser.ms