Difference between revisions of "User:QQuix/Array sample code"
imported>QQuix m (Minor text and code changes) |
imported>QQuix (Converted part of the text to an User Function) |
||
(3 intermediate revisions by the same user not shown) | |||
Line 9: | Line 9: | ||
</dl></dl> | </dl></dl> | ||
=Introduction= | |||
=Array walk= | |||
==Introduction== | |||
This sample code allows walking a tree-like array structure | |||
Useful when one needs to access array data sequentially, one at a time, over many frames. | |||
The code allow for returning the previous or the next entry in the structure. When one branch ends, it jumps to the first entry of the next branch. | |||
This sample works on a multi level, tree like array. Each 'branch' of the tree being a StringMap array. The object at the end of the branch must not be a StringMap. Branches mey have different sizes. | |||
==Setup== | |||
This sample uses the following objects: | |||
* qqArrayWalk - a persistent object that holds the script. | |||
* qqGetNext, qqGetPrev and qqReset - persistent objects to be used as actionref | |||
===Usage=== | |||
To get the next entry: | |||
qqArrayWalk.Activate qqGetNext 1 | |||
let MyObject := qqArrayWalk.aReturnObject | |||
To get the previous entry: | |||
qqArrayWalk.Activate qqGetPrev 1 | |||
let MyObject := qqArrayWalk.aReturnObject | |||
To reset the loop to the first entry of the first branch: | |||
qqArrayWalk.Activate qqGetNext, 1 | |||
let MyObject := qqArrayWalk.aReturnObject | |||
==Script== | |||
scn qqArrayTreeWalkSCRIPT | |||
array_var aReturnObject | |||
ref xSelf | |||
;------------------------------------------------------- | |||
; These arrays hold the branch and key data for each level as the loop goes down a branch | |||
; Used to walk the branch back up | |||
;------------------------------------------------------- | |||
array_var aBranches | |||
array_var aKeys | |||
;------------------------------------------------------- | |||
; These vars hold the current position | |||
;------------------------------------------------------- | |||
array_var aBranch | |||
string_var sKey | |||
short xLevel | |||
string_var sType | |||
short xForward | |||
begin onactivate | |||
if getactionref == qqGetNext | |||
set xForward to 1 | |||
elseif getactionref == qqGetPrev | |||
set xForward to 0 | |||
endif | |||
if getactionref == qqReset || xSelf == 0 | |||
;----------------------------------------------- | |||
; [Re]initialize the loop | |||
;----------------------------------------------- | |||
set xSelf to getself | |||
if aBranches == 0 | |||
let aBranches := ar_construct array | |||
let aKeys := ar_construct array | |||
endif | |||
set xLevel to 0 | |||
let aBranch := g.gaObjectTree ; The array to be walked | |||
let sKey := ar_Last aBranch | |||
set xForward to 1 | |||
endif | |||
if xForward | |||
let sKey := ar_Next aBranch sKey | |||
else | |||
let sKey := ar_Prev aBranch sKey | |||
endif | |||
saveip 4 | |||
if eval ( sKey == ar_BadStringIndex ) | |||
set xLevel to xLevel - 1 | |||
if xLevel >= 0 | |||
;----------------------------------------------------------- | |||
; End of array - go up one level | |||
;----------------------------------------------------------- | |||
let aBranch := aBranches [xLevel] | |||
let sKey := aKeys [xLevel] | |||
if xForward | |||
let sKey := ar_Next aBranch sKey | |||
else | |||
let sKey := ar_Prev aBranch sKey | |||
endif | |||
goto 4 | |||
else | |||
;----------------------------------------------------------- | |||
; End of last array - start over | |||
;----------------------------------------------------------- | |||
set xLevel to 0 | |||
let aBranch := g.gaObjectTree | |||
if xForward | |||
let sKey := ar_First aBranch | |||
else | |||
let sKey := ar_Last aBranch | |||
endif | |||
goto 4 | |||
endif | |||
endif | |||
let sType := typeof aBranch [sKey] | |||
if eval (sType == "StringMap") | |||
;----------------------------------------------------------- | |||
; Entry is an array - go down one level | |||
;----------------------------------------------------------- | |||
let aBranches [xLevel] := aBranch | |||
let aKeys [xLevel] := sKey | |||
set xLevel to xLevel + 1 | |||
let aBranch := aBranch [sKey] | |||
if xForward | |||
let sKey := ar_First aBranch | |||
else | |||
let sKey := ar_Last aBranch | |||
endif | |||
goto 4 | |||
else | |||
;----------------------------------------------------------- | |||
; End of branch - set aReturnObject | |||
;----------------------------------------------------------- | |||
let aReturnObject := aBranch [sKey] | |||
endif | |||
end | |||
=Array deep dump= | |||
<dl> | |||
{| class="wikitable" style="width:90%; text-align:left" | |||
| align="left" width="600"|Deprecated. Replaced by [[ArrayDeepDump]] ([[User Function]]) | |||
|} | |||
</dl> | |||
==Introduction== | |||
With the availability of arrays in OBSE 0017, it is quite easy (an useful) to create tree-like arrays to keep data available and organized. | With the availability of arrays in OBSE 0017, it is quite easy (an useful) to create tree-like arrays to keep data available and organized. | ||
Line 17: | Line 180: | ||
It dumps the array to the console and to a text file (requires Pluggy), but either can be easily removed, if you prefer. It is also easy to customize the contents and formatting to your liking. | It dumps the array to the console and to a text file (requires Pluggy), but either can be easily removed, if you prefer. It is also easy to customize the contents and formatting to your liking. | ||
Optionally, you may limit the number of levels to dump. | |||
It has two modes. | It has two modes. | ||
Line 56: | Line 221: | ||
[ObjectTree][Clutter] = #Empty# | [ObjectTree][Clutter] = #Empty# | ||
=Setup= | ==Setup== | ||
The following script must be attached to some persistent objects. | The following script must be attached to some persistent objects. | ||
Line 77: | Line 242: | ||
let aaqqArrayDump.isArrayName := "ObjectTree" ; set array name - for the header | let aaqqArrayDump.isArrayName := "ObjectTree" ; set array name - for the header | ||
let aaqqArrayDump.iMode := 1 ; set Mode | let aaqqArrayDump.iMode := 1 ; set Mode | ||
let aaqqArrayDump.iDepth := 3 ; Number of levels to dump (0 = All) | |||
aaqqArrayDump.activate player 1 | aaqqArrayDump.activate player 1 | ||
=Script= | ==Script== | ||
scn aaqqArrayDumpSCRIPT | scn aaqqArrayDumpSCRIPT | ||
Line 90: | Line 256: | ||
array_var gaKeys | array_var gaKeys | ||
array_var gaArrays | array_var gaArrays | ||
short gMaxLevel | |||
ref xSelf | ref xSelf | ||
Line 116: | Line 283: | ||
short xLevel | short xLevel | ||
short xNextLevel | short xNextLevel | ||
short xMaxLevel | |||
;=== Pluggy string vars === | ;=== Pluggy string vars === | ||
Line 177: | Line 345: | ||
if xLevel == 0 | if xLevel == 0 | ||
;=== Init MaxLevel === | |||
;============== | |||
set gMaxLevel to iDepth - 1 | |||
if gMaxLevel < 0 || xMaxLevel > 5 | |||
set gMaxLevel to 5 | |||
endif | |||
;=== Print Header === | ;=== Print Header === | ||
;============== | ;============== | ||
let sLine := "===== Deep dump Mode " + ( tostring iMode ) + " - | let sLine := "===== Deep dump Mode " + ( tostring iMode ) + " - Depth= " + ( tostring gMaxLevel + 1 ) + " - Array: [" + gaKeys [0] + "] =====" | ||
printc "PrintArray>> %z " sLine | |||
setString psLine $sLine | setString psLine $sLine | ||
StringToTxtFile psFile | StringToTxtFile psFile psLine | ||
endif | endif | ||
set xMaxLevel to aaqqArrayDump.gMaxLevel | |||
;=== Setup array and key === | ;=== Setup array and key === | ||
Line 202: | Line 377: | ||
if iMode == 2 | if iMode == 2 | ||
let sLine := sKey + " = " + "#Empty#" | let sLine := sKey + " = " + "#Empty#" | ||
printc "PrintArray>> %z " sLine | |||
setString psLine $sLine | setString psLine $sLine | ||
StringToTxtFile psFile psLine | StringToTxtFile psFile psLine | ||
Line 266: | Line 441: | ||
StringToTxtFile psFile psLine | StringToTxtFile psFile psLine | ||
endif | endif | ||
if | if xLevel < xMaxLevel ; stops recursion at the last level initialized | ||
set xNextLevel to xLevel + 1 | set xNextLevel to xLevel + 1 | ||
let aaqqArrayDump.gaKeys [xNextLevel] := sKey1 | let aaqqArrayDump.gaKeys [xNextLevel] := sKey1 | ||
Line 273: | Line 448: | ||
ar_Erase aaqqArrayDump.gaKeys xNextLevel | ar_Erase aaqqArrayDump.gaKeys xNextLevel | ||
ar_Erase aaqqArrayDump.gaArrays xNextLevel | ar_Erase aaqqArrayDump.gaArrays xNextLevel | ||
elseif xLevel == xMaxLevel && iMode == 2 | |||
let sLine := sKey + "[" + sKey1 + "]" + " . . ." | |||
printc "PrintArray>> %z " sLine | |||
setString psLine $sLine | |||
StringToTxtFile psFile psLine | |||
endif | endif | ||
endif | endif |
Latest revision as of 15:14, 2 August 2009
This is a piece of code I wrote for my tests and thought might be of use to somebody else.
Feel free to edit/rephrase/correct/rename/move/whatever the contents of this page as you see fit. QQuix 18:38, 24 May 2009 (EDT) |
Array walk[edit | edit source]
Introduction[edit | edit source]
This sample code allows walking a tree-like array structure
Useful when one needs to access array data sequentially, one at a time, over many frames.
The code allow for returning the previous or the next entry in the structure. When one branch ends, it jumps to the first entry of the next branch.
This sample works on a multi level, tree like array. Each 'branch' of the tree being a StringMap array. The object at the end of the branch must not be a StringMap. Branches mey have different sizes.
Setup[edit | edit source]
This sample uses the following objects:
- qqArrayWalk - a persistent object that holds the script.
- qqGetNext, qqGetPrev and qqReset - persistent objects to be used as actionref
Usage[edit | edit source]
To get the next entry:
qqArrayWalk.Activate qqGetNext 1 let MyObject := qqArrayWalk.aReturnObject
To get the previous entry:
qqArrayWalk.Activate qqGetPrev 1 let MyObject := qqArrayWalk.aReturnObject
To reset the loop to the first entry of the first branch:
qqArrayWalk.Activate qqGetNext, 1 let MyObject := qqArrayWalk.aReturnObject
Script[edit | edit source]
scn qqArrayTreeWalkSCRIPT array_var aReturnObject ref xSelf ;------------------------------------------------------- ; These arrays hold the branch and key data for each level as the loop goes down a branch ; Used to walk the branch back up ;------------------------------------------------------- array_var aBranches array_var aKeys ;------------------------------------------------------- ; These vars hold the current position ;------------------------------------------------------- array_var aBranch string_var sKey short xLevel string_var sType short xForward begin onactivate if getactionref == qqGetNext set xForward to 1 elseif getactionref == qqGetPrev set xForward to 0 endif if getactionref == qqReset || xSelf == 0 ;----------------------------------------------- ; [Re]initialize the loop ;----------------------------------------------- set xSelf to getself if aBranches == 0 let aBranches := ar_construct array let aKeys := ar_construct array endif set xLevel to 0 let aBranch := g.gaObjectTree ; The array to be walked let sKey := ar_Last aBranch set xForward to 1 endif if xForward let sKey := ar_Next aBranch sKey else let sKey := ar_Prev aBranch sKey endif saveip 4 if eval ( sKey == ar_BadStringIndex ) set xLevel to xLevel - 1 if xLevel >= 0 ;----------------------------------------------------------- ; End of array - go up one level ;----------------------------------------------------------- let aBranch := aBranches [xLevel] let sKey := aKeys [xLevel] if xForward let sKey := ar_Next aBranch sKey else let sKey := ar_Prev aBranch sKey endif goto 4 else ;----------------------------------------------------------- ; End of last array - start over ;----------------------------------------------------------- set xLevel to 0 let aBranch := g.gaObjectTree if xForward let sKey := ar_First aBranch else let sKey := ar_Last aBranch endif goto 4 endif endif let sType := typeof aBranch [sKey] if eval (sType == "StringMap") ;----------------------------------------------------------- ; Entry is an array - go down one level ;----------------------------------------------------------- let aBranches [xLevel] := aBranch let aKeys [xLevel] := sKey set xLevel to xLevel + 1 let aBranch := aBranch [sKey] if xForward let sKey := ar_First aBranch else let sKey := ar_Last aBranch endif goto 4 else ;----------------------------------------------------------- ; End of branch - set aReturnObject ;----------------------------------------------------------- let aReturnObject := aBranch [sKey] endif end
Array deep dump[edit | edit source]
Deprecated. Replaced by ArrayDeepDump (User Function) |
Introduction[edit | edit source]
With the availability of arrays in OBSE 0017, it is quite easy (an useful) to create tree-like arrays to keep data available and organized.
OBSE 0017 also has a great debugging function to dump an array contents into the console: ar_Dump
This code has the same debugging purpose as ar_Dump, but intended to show the contents of nested arrays, or arrays within arrays.
It dumps the array to the console and to a text file (requires Pluggy), but either can be easily removed, if you prefer. It is also easy to customize the contents and formatting to your liking.
Optionally, you may limit the number of levels to dump.
It has two modes.
Mode 1[edit | edit source]
Shows the Keys within brackets, followed by: #Array ID and array size (if an array) or the contents
===== Deep dump Mode 1 - Array: [ObjectTree] ===== [Architecture] #410 2 = [Anvil] #415 3 = = [AnvilFightersGuild01] #416 3 = = = [EditorID] = 'AnvilFightersGuild01' = = = [FormID] = 000496C5 <no name> = = = [Size] = 22 = = [AnvilHouseMC01] #417 0 = = [AnvilLighthouse01] #418 0 = [Chorrol] #419 1 = = [Interior] #420 1 = = = [ChorrolHouseMiddle03Interior] #421 3 = = = = [EditorID] = 'ChorrolHouseMiddle03Interior' = = = = [FormID] = 0002B75F <no name> = = = = [Size] = 11 [Clutter] #414 0
Mode 2[edit | edit source]
Shows one line for every end-of branch
===== Deep dump Mode 2 - Array: [ObjectTree] ===== [ObjectTree][Architecture][Anvil][AnvilFightersGuild01][EditorID] = 'AnvilFightersGuild01' [ObjectTree][Architecture][Anvil][AnvilFightersGuild01][FormID] = 000496C5 <no name> [ObjectTree][Architecture][Anvil][AnvilFightersGuild01][Size] = 22 [ObjectTree][Architecture][Anvil][AnvilHouseMC01] = #Empty# [ObjectTree][Architecture][Anvil][AnvilLighthouse01] = #Empty# [ObjectTree][Architecture][Chorrol][Interior][ChorrolHouseMiddle03Interior][EditorID] = ChorrolHouseMiddle03Interior' [ObjectTree][Architecture][Chorrol][Interior][ChorrolHouseMiddle03Interior][FormID] = 0002B75F <no name> [ObjectTree][Architecture][Chorrol][Interior][ChorrolHouseMiddle03Interior][Size] = 11 [ObjectTree][Clutter] = #Empty#
Setup[edit | edit source]
The following script must be attached to some persistent objects.
You need one object for each level of array depth you may have.
The first object handles arrays at level 0 and also holds the 'global' variables used for iteration. A different object handles level 1 and so forth.
For this example, we are considering a 5-level deep array called ObjectTree.
It is presumed that:
- six activators were created called: aaqqArrayDumpBase and aaqqArrayDumpL1Base to aaqqArrayDumpL5Base. All six base objects use the same script.
- six persistent references were created called aaqqArrayDump and aaqqArrayDumpL1 to aaqqArrayDumpL5
This code shows how to set the variables and activate the first object:
array_var aLibObjectTree let aaqqArrayDump.iaArray := aLibObjectTree ; set array to dump let aaqqArrayDump.isArrayName := "ObjectTree" ; set array name - for the header let aaqqArrayDump.iMode := 1 ; set Mode let aaqqArrayDump.iDepth := 3 ; Number of levels to dump (0 = All) aaqqArrayDump.activate player 1
Script[edit | edit source]
scn aaqqArrayDumpSCRIPT array_var iaArray string_var isArrayName short iMode array_var gaKeys array_var gaArrays short gMaxLevel ref xSelf ref xNext ref xRef array_var aArray array_var aEntry array_var aTemp string_var sKey string_var sKey1 string_var sType string_var sText string_var sLine string_var sTab string_var sTab0 string_var sTab1 string_var sTab2 string_var sTab3 string_var sTab4 string_var sTab5 float xVal short xLevel short xNextLevel short xMaxLevel ;=== Pluggy string vars === long psFile long psLine begin onactivate set iMode to aaqqArrayDump.iMode if xSelf == 0 || getgameloaded ;=== Initialize === ;============== set xSelf to getself set psFile to CreateString -1 "QQuix Library - Array dump.log" 1 1 set psLine to CreateString -1 0 1 1 let sTab0 := "" let sTab1 := "= " let sTab2 := "= = " let sTab3 := "= = = " let sTab4 := "= = = = " let sTab5 := "= = = = =" if xSelf == aaqqArrayDump set xLevel to 0 let sTab := sTab0 set xNext to aaqqArrayDumpL1 ;=== Init 'global' vars === let gaKeys := ar_Construct Array let gaArrays := ar_Construct Array let gaKeys [0] := isArrayName let gaArrays [0] := iaArray elseif xSelf == aaqqArrayDumpL1 set xLevel to 1 let sTab := sTab1 set xNext to aaqqArrayDumpL2 elseif xSelf == aaqqArrayDumpL2 set xLevel to 2 let sTab := sTab2 set xNext to aaqqArrayDumpL3 elseif xSelf == aaqqArrayDumpL3 set xLevel to 3 let sTab := sTab3 set xNext to aaqqArrayDumpL4 elseif xSelf == aaqqArrayDumpL4 set xLevel to 4 let sTab := sTab4 set xNext to aaqqArrayDumpL5 elseif xSelf == aaqqArrayDumpL5 set xLevel to 5 let sTab := sTab5 set xNext to 0 ;=== Add additional ElseIf's here to to handle deeper arrays === endif endif if xLevel == 0 ;=== Init MaxLevel === ;============== set gMaxLevel to iDepth - 1 if gMaxLevel < 0 || xMaxLevel > 5 set gMaxLevel to 5 endif ;=== Print Header === ;============== let sLine := "===== Deep dump Mode " + ( tostring iMode ) + " - Depth= " + ( tostring gMaxLevel + 1 ) + " - Array: [" + gaKeys [0] + "] =====" printc "PrintArray>> %z " sLine setString psLine $sLine StringToTxtFile psFile psLine endif set xMaxLevel to aaqqArrayDump.gMaxLevel ;=== Setup array and key === ;======================= let aArray := aaqqArrayDump.gaArrays [xLevel] if iMode == 1 let sKey := aaqqArrayDump.gaKeys [xLevel] else let sKey := "" foreach aEntry <- aaqqArrayDump.gaKeys let sKey := sKey + "[" + aEntry [Value] + "]" loop endif if 0 == ar_size aArray ;=== Empty array === ;================= if iMode == 2 let sLine := sKey + " = " + "#Empty#" printc "PrintArray>> %z " sLine setString psLine $sLine StringToTxtFile psFile psLine endif else foreach aEntry <- aArray ;=== Get key === ;============= let sType := typeof aEntry [Key] if eval (sType == "String") let sKey1 := aEntry [Key] else let sKey1 := tostring aEntry [Key] endif let sType := typeof aEntry [Value] if eval (sType == "String") ;=== Print string contents === ;======================= let sText := aEntry [Value] if iMode == 1 let sLine := sTab + "[" + sKey1 + "]" + " = '" + sText + "'" else let sLine := sKey + "[" + sKey1 + "]" + " = '" + sText + "'" endif printc "PrintArray>> %z " sLine setString psLine $sLine StringToTxtFile psFile psLine elseif eval (sType == "Number") ;=== Print number contents === ;========================= let xVal := aEntry [Value] if iMode == 1 let sLine := sTab + "[" + sKey1 + "]" + " = " + tostring xVal else let sLine := sKey + "[" + sKey1 + "]" + " = " + tostring xVal endif printc "PrintArray>> %z " sLine setString psLine $sLine StringToTxtFile psFile psLine elseif eval (sType == "Form") ;=== Print form contents === ;========================= let xRef := aEntry [Value] set sText to sv_Construct "%i %n" xRef xRef if iMode == 1 let sLine := sTab + "[" + sKey1 + "]" + " = " + sText else let sLine := sKey + "[" + sKey1 + "]" + " = " + sText endif printc "PrintArray>> %z " sLine setString psLine $sLine StringToTxtFile psFile psLine else ;=== Print array contents === ;========================= if iMode == 1 let aTemp := aEntry[Value] let sLine := sTab + "[" + sKey1 + "] #" + sv_construct "%g" aTemp + " " + ( tostring ar_size ( aEntry [Value] ) ) printc "PrintArray>> %z " sLine setString psLine $sLine StringToTxtFile psFile psLine endif if xLevel < xMaxLevel ; stops recursion at the last level initialized set xNextLevel to xLevel + 1 let aaqqArrayDump.gaKeys [xNextLevel] := sKey1 let aaqqArrayDump.gaArrays [xNextLevel] := aEntry [Value] xNext.activate2 xSelf 1 ar_Erase aaqqArrayDump.gaKeys xNextLevel ar_Erase aaqqArrayDump.gaArrays xNextLevel elseif xLevel == xMaxLevel && iMode == 2 let sLine := sKey + "[" + sKey1 + "]" + " . . ." printc "PrintArray>> %z " sLine setString psLine $sLine StringToTxtFile psFile psLine endif endif loop endif end