Script for å repetere animasjonskeys (walk cycles ol)

Max scripts

Moderatorer: Super Moderatorer, Admins


Trådstarter
hardrock_ram
Innlegg: 1502
Registrert: ons 07 feb, 2007
Sted: Kristiansand

Script for å repetere animasjonskeys (walk cycles ol)

Legg innav hardrock_ram » søn 26 feb, 2012

Skrev dette scriptet for å repetere keyframes og tilhørende verdier, fordi det ble alltid litt småkluss og rot når jeg skulle gjøre dette i curve editor over mange objekter. Scriptet er altså beregnet på meg selv, og er dermed ikke idiotsikkert (for de som er mer idioter enn meg :P). Tar gjerne imot tilbakemeldinger, men det er i utgangspunktet ment til et spesielt behov i en spesiell scene for meg. Legger det ut her i tilfelle andre synes det er kjekt, så kan folk editere det som de vil.

*Scriptet takler listekontrollere, toveis wiring, limited controller, Custom attributes som ligger i emptyModifier og link constraint.
Den "endelige" kontrolleren må være bezier float (vanlig). Man kan fint ha andre kontrollere i tillegg (TCB ol.), men disse vil scriptet bare hoppe over.
*Scripet vil legge til verdier på posisjonskeys på objekter som ikke har parent. Dette er ment for føtter ol. som går framover. For alle andre objekter sørger den for at siste key har lik verdi som første key for å få en repeterende syklus. Kriteriene for dette kan enkelt forandres i if-then-else statement på linje 215.
*Scriptet skal ta vare på type tangent som er satt til hver key, men av en eller annen merkelig grunn så kan den begynne å bruke default tangenter isteden. Dette kan skje når som helst, og midt ut i scriptet, dvs. at den greier å sette tangentene til noen keys riktig, mens den setter default på andre. Akkurat dette problemet får meg til å hate en del :P

[spoiler]

Kode: Velg alt

--CYCLE REPEATER

/*
gjøreliste:

*Den må kunne identifisere modifiere for å sjekke at de ikke har blitt kjørt script over fra før hvis de for eks. er instance over flere objekter
(ikke fikset. Løses foreløpig ved å skrive inn et nøyaktig tidsvindu for første og siste frame. Da vil den bare overkjøre keyverdier som er lagt inn fra før)

*Den må kunne kontrollere om et objekt skal ha valueAdd på pos eller ikke (kjører kun valueAdd på objekter som ikke har parent)

*Den greier ikke alltid å ta vare på tangenter, og vil etterhvert sette tangenter til default type

*/


Rollout cycleRepeater "Cycle Repeater"
(   
   --Interface
   button btn_addSelObjects "Add selected objects"
   button btn_removeSel "Remove selected objects"
   button btn_empty "Remove all objects"
   button btn_printObjects "Print objects"
   spinner spn_cycleStart "Cycle start frame" type:#integer range: [-9999,9999,currentTime]
   spinner spn_cycleEnd "Cycle end frame" type:#integer range: [-9999,9999,currentTime]
   button btn_execute "Execute"
   
   --Variabler
   local myObjects =#() -- For å ta vare på objekter som hele tiden plusser på verdiene for hver syklus
   
   --Hendelser
   on btn_addSelObjects pressed do -- Man legger til valgte objekter i array
   (
      for sel = selection do
      (
         appendIfUnique myObjects sel
      )
   )
   
   on btn_removeSel pressed do
   (
      for sel = selection do
      (
         indexnr = (findItem myObjects sel)
         deleteItem myObjects indexnr
      )            
   )
   
   on btn_empty pressed do -- Hva skjer når man trykker på knappen for å fjerne alle objekter i lista
   (
      free myObjects
   )
   
   on btn_printObjects pressed do -- Hva skjer når man trykker knappen for å printe alle parents
   (
      for i = myObjects do print i.name
   )
   
   on btn_execute pressed do -- SCRIPTET KJØRES
   (
      fn masterFunction currentObj currentAxis subControllerCount posRotCust =
      --Hovedfunksjonen for å hente ut keys og verdier, forskyve dem, og legge dem tilbake. Argumentene blir satt på slutten, når funksjonen kalles på.
      (
         --Variabler for å forenkle språket i scriptet
         local fromTime = spn_cycleStart.value as integer --Forenkler språket for å indikere oppstartstid
         local toTime = spn_cycleEnd.value as integer --Forenkler språket for å indikere stopptid
         local runningTime = (spn_cycleEnd.value) - (spn_cycleStart.value) -- Forenkler språket ved å indikere oppstartstid og tidsvinduet for scriptet
         
         
         --Arrays for å ta vare på frames som inneholder keys, og deres verdier
         local frameWithKeyArray = #() -- Alle Frames som har en tilhørende key
         local valueArray = #() --Tilhørende verdier til frames
         
         
         --Arrays for å ta vare på tangenter som skal legges tilbake på keys
         local inTangentTypeArray = #()
         local outTangentTypeArray = #()
         
         local inTangentArray = #()
         local outTangentArray =#()
         
         local inTangentLengthArray = #()
         local outTangentLengthArray =#()
         
         
         --Variabler som har betydning for hvordan scriptet kjøres, hvilke deler som hoppes over etc.
         local modifierRuns = 0 --variabel som inneholder antall modifiere med customAttributes
         local emptyModifierPresent = false --variabel som indikerer at det eksisterer en empty modifier på objektet
         local custAttributesPresent = false --variabel som indikerer at det eksisterer custom attributes på empty modifier
         local custAttributesRuns = 1 --Antall sett med custom attributes som eksisterer på modifieren
         local custAttributeSubPresent = false --variabel som indikerer om det er en "sub-controller" som eksisterer med toveis wiring
         local runs = 1 --variabel som indikerer hvor mange kontrollere det må sjekkes for keys
         local currentController --variabel som skal inneholde kontrolleren det jobbes på
         
         
         if (posRotCust== "pos" or posRotCust == "rot") and subControllerCount == 0 do runs = 1 --null på subControllerCount indikerer at det ikke er noen list_controller
         if (posRotCust== "pos" or posRotCust == "rot") and subControllerCount >0 do runs = subControllerCount -- indikerer at det ER en list_controller i subControllerCount
         
         if posRotCust == "cust" do -- Hvis posRotCust indikerer at det skal gjøres operasjoner på customAttributes ("Cust")
         (
            --Først må det telles antall modifiere som inneholder custom attributes. Dette settes i "modifierRuns"
            for i = currentObj.modifiers where classOf i == EmptyModifier do
            (
               modifierRuns += 1
               emptyModifierPresent = true --indikerer at det er en modifiertype som typisk inneholder custom attribtues
            )
         )
         
         if modifierRuns <1 do modifierRuns = 1 --Hvis det ikke eksisterer noen empty modifier, så må kommende setning allikevel kjøres en gang
         for currentModifier = 1 to modifierRuns do
         (
            try (if (emptyModifierPresent == true) and ((custAttributes.count currentObj.modifiers[currentModifier]) >0) do custAttributesPresent = true) catch ()
            --Hvis det eksisterer custom attributes, så blir custAttributesPresent = true. Try\catch eksisterer fordi det gir feilmelding å telle custom attributes hvis de ikke eksisterer.
            --Ved "catch" vil custAttributesPresent forbli "false".
            
            if custAttributesPresent == true do
            -- Hvis custAttributesPresent indikerer at det eksisterer custom attributes, så kjøres setningen under
            (
               --Det telles antall sett med customAttributes. Dette settes i "custAttributesRuns"
               custAttributesRuns = custAttributes.count currentObj.modifiers[currentModifier]
            )
            
            
            
            for currentCustomAttribute = 1 to custAttributesRuns do
            --Kjøres over antall custom attributes. Den må uansett kjøres en gang, som er grunnen til at custAttributesRuns har defaultverdi på 1.
            (
               if custAttributesPresent == true do
               -- Hvis custAttributesPresent indikerer at det eksisterer custom attributes, så vil den i neste setning telle antall enkeltattributter, og putte antallet i variabel "runs"
               (
                  while ((custAttributes.get currentObj.modifiers[currentModifier] currentCustomAttribute)[runs]) != undefined do runs += 1
                  if runs >1 do runs -= 1 --Sørger for at "runs" får korrekt nummer. I setningen over vil den alltid ha en(1) verdi høyere enn den skal
               )
               
               
               
               for currentControllerIndex = 1 to runs do -- Det kjøres en loop over alle controllere, eller evt. alle enkeltattributter
               (
                  --Gir currentController korrekt oppsett hvis det ikke dreier seg om custom attribute
                  try (if classOf currentObj.controller != Link_Constraint and subControllerCount == 0 and posRotCust == "pos" do currentController = currentObj.controller.position.controller[currentAxis].controller) catch (currentController = undefined)
                  try (if classOf currentObj.controller != Link_Constraint and subControllerCount > 0 and posRotCust == "pos" do currentController = currentObj.controller.position.controller[currentControllerIndex][currentAxis].controller) catch (currentCOntroller = undefined)
                  if classOf currentObj.controller == Link_Constraint and subControllerCount == 0 and posRotCust == "pos" do currentController = currentObj.controller.link_params.position.controller[currentAxis].controller
                     
                  try (if classOf currentObj.controller != Link_Constraint and subControllerCount == 0 and posRotCust == "rot" do currentController = currentObj.controller.rotation.controller[currentAxis].controller) catch (currentController = undefined)
                  try (if classOf currentObj.controller != Link_Constraint and subControllerCount > 0 and posRotCust == "rot" do currentController = currentObj.controller.rotation.controller[currentControllerIndex][currentAxis].controller) catch (currentCOntroller = undefined)
                  if classOf currentObj.controller == Link_Constraint and subControllerCount == 0 and posRotCust == "rot" do currentController = currentObj.controller.link_params.rotation.controller[currentAxis].controller
                  
                  try (if classof currentController == float_limit do currentController = currentController[1].controller) catch()--Legger til subcontroller hvis det er limited controller
                  
                  try (if classof currentController == Float_Wire do currentController = currentController[1].controller) catch() --Legger til subcontroller på currentController hvis det er toveis wiring
                  
                  --Hvis det dreier seg om custom attribute:
                  --Først finner den ut om den kjøres på et custom attribute, og hvis den gjør det, så sjekker den om det er en subcontroller tilstede. Kontrolleren vil dermed bli riktig i "currentController"
                  --Hvis posRotCust indikerer at den kjører på "cust", men ikke har noen custom attributes, så vil currentController bli satt til undefined, og ingenting vil skje
                  if custAttributesPresent == true do
                  (
                     try
                     (
                        if (custAttributes.get currentObj.modifiers[currentModifier] currentCustomAttribute)[currentControllerIndex][1] != undefined then
                        (
                           currentController = (custAttributes.get currentObj.modifiers[currentModifier] currentCustomAttribute)[currentControllerIndex][1].controller
                        )
                        else
                        (
                           currentController = (custAttributes.get currentObj.modifiers[currentModifier] currentCustomAttribute)[currentControllerIndex].controller
                        )
                     )
                     catch(currentController = undefined)
                  )
                  
                  
                  if currentController != undefined and classof currentController == bezier_float and \
                     currentController.keyable == true and currentController.keys.count >0 do -- sjekker at kontrolleren IKKE er boolean_float , og at det er keys
                  (
                     --Arrays med keys og verdier fylles
                     for keyNumber = 1 to numKeys currentController do
                     (
                        frameWithKey = ((((getKeyTime currentController keyNumber as float) / 4800) * frameRate) as integer)
                        if frameWithKey >= fromTime and frameWithKey <= toTime then
                        (
                           --Frames med keys puttes i array
                           append frameWithKeyArray frameWithKey
                           
                           --Den tilhørende verdien for kontrolleren puttes i array
                           append valueArray (currentController.keys[keyNumber].value)
                           
                           --Tangentene puttes i et array
                           tangentObj = currentController.keys[keyNumber] --gjeldende objekt og key:
                           
                           append inTangentTypeArray tangentObj.inTangentType
                           append outTangentTypeArray tangentObj.outTangentType
                           append inTangentArray tangentObj.inTangent
                           append outTangentArray tangentObj.outTangent
                           append inTangentLengthArray tangentObj.inTangentLength
                           append outTangentLengthArray tangentObj.outTangentLength
                        )
                     )
                     
                     if frameWithKeyArray.count >0 do
                     -- Sjekker at det er keys i frameWithKeyArray. Selv om det er keys på kontrolleren, så kan de være utenfor vinduet som er satt i spn_cycleStart\End
                     (
                        --Forskyvelse av keys:
                        local lastKeyInArray = frameWithKeyArray.count -- lastKeyInArray er høyeste indexverdi i arrayet. Det er IKKE frame-nummer.
                        local frameDifference = frameWithKeyArray[lastKeyInArray] - frameWithKeyArray[1] --frameDifference blir "forskyvningsverdien" som alle keys skal ha
                        
                        for i = 1 to lastKeyInArray do
                        (
                           frameWithKeyArray[i] += frameDifference --Forskyvningsverdien legges på keys
                        )
                        
                        --Forskyvelse av verdier:
                        local numberOfValues = valueArray.count --Variabel som inneholder max indexnr i arrayet valueArray
                        valueAdd = valueArray[numberOfValues] - valueArray[1] -- valueAdd er verdien som skal legges til på alle keys
                        
                        
                        if posRotCust == "pos" and currentObj.parent == undefined then --Posisjon skal ha verdier som legges til for stadig økning av verdien.
                        (
                           for i = 1 to numberOfValues do
                           (
                              valueArray[i] += valueAdd --verdiene legges til til hver enkelt verdi i valueArray
                           )
                        )
                        else -- "rot" og "cust" skal IKKE ha verdiøkning, og siste verdi skal være lik første verdi i valueArray. ValueAdd brukes derfor ikke.
                        (
                           valueArray[numberOfValues] = valueArray[1] --Siste verdi blir lik første verdi.
                        )
                        
                        
                        
                        --nye keyframes legges tilbake på kontrolleren
                        for i = 1 to lastKeyInArray do
                        (
                           addNewKey currentController frameWithKeyArray[i]
                           
                           -- verdier for keys legges på
                           with animate on
                           (
                              at time frameWithKeyArray[i] currentController.value = valueArray[i]
                           )
                           
                           --Keys får riktige tangenter
                           tangentObj = currentController.keys[(lastKeyInArray + i - 1)] --gjeldende objekt og key:
                           
                           tangentObj.inTangentType = inTangentTypeArray[i]
                           tangentObj.outTangentType = outTangentTypeArray[i]
                           
                           --Retning skal kun redigeres hvis tangenten er #custom (spline i interfacet)
                           if tangentObj.inTangentType == #custom do
                           (
                              tangentObj.inTangent = inTangentArray[i]
                              tangentObj.inTangentLength =  inTangentLengthArray[i]
                           )
                           
                           --Lengde skal kun redigeres hvis tangenten er #custom (spline i interfacet)
                           if tangentObj.outTangentType == #custom do
                           (
                              tangentObj.outTangent = outTangentArray[i]
                              tangentObj.outTangentLength = outTangentLengthArray[i]
                           )
                        )
                     )
                  )
                  
                  
                  --Arrays tømmes for å klargjøres til neste kontroller
                  free frameWithKeyArray
                  free valueArray
                  
                  free inTangentTypeArray
                  free outTangentTypeArray
                  free inTangentArray
                  free outTangentArray
                  free inTangentLengthArray
                  free outTangentLengthArray
               )--Slutt på loop over runs
            )--Slutt på loop over custAttributesRuns
         )--Slutt på loop over modifierRuns
      ) -- slutt på masterFunction
      
      
      for obj = myObjects do --Loop som kjøres på alle objekter i myObjects - arrayet. Her kjøres POS
      (
         local subControllerCount = 0 --Defaultverdi. Indikerer at det IKKE er noen list_controller. 1 eller flere indikerer list_controller og antall sub-controllere
         
         try (if classOf obj.controller.position.controller == position_list do subControllerCount = obj.controller.position.controller.count) catch ()
         --Forandrer subControllerCounts verdi for å indikere at det er list_controller, og antall sub-controllere
         
         for axis = 1 to 3 do -- Loop som kjører gjennom XYZ-aksene
         (
            masterFunction obj axis subControllerCount "pos" -- Funksjonen kjøres
         )
      )
      
      
      
      
      for obj = myObjects do --Loop som kjøres på alle objekter i myObjects - arrayet. Her kjøres ROT
      (
         local subControllerCount = 0 --Defaultverdi. Indikerer at det IKKE er noen list_controller. 1 eller flere indikerer list_controller og antall sub-controllere
         
         try (if classOf obj.controller.rotation.controller == rotation_list do subControllerCount = obj.controller.rotation.controller.count) catch ()
         --Forandrer subControllerCounts verdi for å indikere at det er list_controller, og antall sub-controllere
         
         for axis = 1 to 3 do -- Loop som kjører gjennom XYZ-aksene
         (
            masterFunction obj axis subControllerCount "rot" -- Funksjonen kjøres
         )
      )
      
      
      
      
      for obj = myObjects do --Loop som kjøres på alle objekter i myObjects - arrayet. Her kjøres CUST
      (
         local subControllerCount = 0 --Defaultverdi. Denne er det ingen bruk for i "cust", men det må være en defaultverdi allikevel
         
         masterFunction obj axis subControllerCount "cust" -- Funksjonen kjøres
         
      )
   )
) createDialog cycleRepeater 200 200 --Dialogboksen opprettes
[/spoiler]
if your not living on a killing ground, you better make your own

Gå tilbake til «Max scripts»

Hvem er online

Brukere i dette forumet: Ingen registrerte brukere og 1 gjest

cron