Updating Custom Attributes to use AttribID

Posted Jan 22, 2017
Last Updated Jan 25, 2017

I'm in the middle of updates for the next major version of of Wall Worm. One of the goals is to make the project more compact and easy to maintain. Part of the strategy is to update custom attributes used in the tools to use AttribID. There are pros and cons to this decision as well as roadblocks.

Private Custom Attributes (Excluding AttribID)

Cons

  • File sizes can balloon (each object in a scene gets a snapshot of the definition for the custom attribute)
  • Harder to maintain -- to update an existing custom attribute rules, functions must be run to update definitions in scenes.

Including AttribID

Pros

  • Easy to maintain: updating a single definition file updates all instances in all scenes as soon as the definition file is updated (just like updating a scripted plugin).
  • Smaller file size. There is only one global definition of the custom attribute that instances derive from. In scenes with hundreds or thousands of custom attribute usages, this can lead to hundreds of megabytes (or more) of file space. (For example, in the case of Wall Worm, each game entity node requires a custom attribute, as well as each displacement, etc. This can add up fast in large scenes.)

In the case of Wall Worm, the pros outweighed the cons, which led me to start this transition.

Transitioning from no AttribID

Converting a custom attribute from one that uses no AttribID to one that does has a major problem: you cannot redefine an existing custom attribute definition on an object with a mismatched AttribID! This means you cannot simply add an attribID to the custom attribute and use the standard custAttributes.redefine() method.

To solve this problem, I wrote the function below, which you can use to update your custom attributes.

/*
This function will update a custom attribute from a version with no attribID to one that has an attribID

obj = the object to inspect
caIndex = the index of the current CA that is being replaced
oldCADef = the definition of existing CA
newCAwithID = the CA that is replacing it and has an attribID

::wallworm_redefine_ca obj caIndex (custAttributes.getDef obj caIndex) newCAwithID
*/

function wallworm_redefine_ca obj caIndex oldCADef newCAwithID = (
 if newCAwithID!= undefined then (
  local ca = custAttributes.get obj caIndex
  custAttributes.add obj newCAwithID
  local newCA = custAttributes.get obj (custAttributes.count obj)
  local defs = custAttributes.getPBlockDefs oldCADef
  for pbi = 1 to defs.count do (
   local paramb = defs[pbi]
   for pbin2 = 5 to paramb.count do (
    local param = (paramb[pbin2][1] as String)
    if isProperty ca param then (
     V = getProperty ca param
     if V != undefined then (
      local newcl = classOf (getProperty newCA param)
      try (
       if newcl != UndefinedClass AND (V as newcl != undefined) then (
        V = V as (newcl)
       )
       setProperty newCA param V
      ) catch (
       --this might happen if the data type changed and there was no valid conversion
       setUserProp obj ("ent_"+param) (V as string)
       format "%\n" (getCurrentException())
      )
     )
    )
   )
  )
  custAttributes.delete obj caIndex
 )
)

Comment

No HTML Tags are permitted.

Angry Teapot Level Design Awards

Newsletter Subscription