ObjectOrientedRef.scr
This script is an interesting use of table tags in LUA to allow direct access to ECOTECT model data in a way similar to object-oriented classes. By over-riding the gettable functions, it is possible to intercept references to entries in some global tables and pre-populate them with data corresponding to the actual entity in the ECOTECT data model.
This means that it is possible to access details about the 2nd zone by using the nomenclature eco.zone[2]. Thus, you could use:
-- New access format. pt = eco.object[1].node[4].pos print(eco.zone[2].volume)
instead of:
pt = {} -- Existing access format. pt.x, pt.y, pt.z = get("object.node.position", 1, 4) print(get("zone.volume", 2))
The following code demonstrates read-only data access for zones, objects and nodes. Materials, schedules and other entities will be added soon, as will setting property values. In fact, this nomenclature will likely be added as the standard means of referencing ECOTECT data in version 6.0 in the future.
Script Contents (Lang: lua)
-- --------------------------------------------
-- This script allows you to access ECOTECT data
-- as objects int your scripts. For example, you
-- can use the following notation:
-- eco.zone[4].volume
-- eco.object[15].area
-- eco.object[15].node[3].pos.y
-- eco.node[3].pos.y
-- --------------------------------------------
-- [[header-start]] --
_EcoTag_Main = newtag()
_EcoTag_Tables = newtag()
-- This function manages model data.
function _EcoGetTableData(table, index)
-- Check for metadata and get value.
local metadata = rawget(table, "_metadata");
local value = rawget(table, index);
-- Return an existing value.
if type(value) ~= "nil" then
return value
end
-- Check for table[index].
if type(index) == "number" then
-- Check for object.node table.
if metadata["type"] == "node" then
if type(metadata["offset"]) == "number"
and metadata["offset"] > 0 then
index = index + metadata["offset"]
end
end
-- Compare with existing index.
if index ~= metadata["index"] then
-- Application data.
if metadata["type"] == "zone" then
table = getZoneData(index)
elseif metadata["type"] == "object" then
table = getObjectData(index)
table.node = {
["_metadata"] = {
["type"] = "node",
["offset"] = table.firstNode
}
}
settag(table.node, _EcoTag_Tables)
elseif metadata["type"] == "node" then
table = getNodeData(index)
table.node = nil
end
-- Metadata.
table["_metadata"] = {
["type"] = metadata["type"],
["index"] = index
}
end
return table
end
return nil
end
-- This function manages the 'eco' table.
function _EcoManageMainTable(table, index)
local value = rawget(table, index);
-- Check for existing value.
if type(value) ~= "nil" then
return value
end
-- Check to create child tables.
if type(index) == "string" then
-- eco.zone.
if index == "zone" then
if type(value) ~= "table" then
table.zone = {
["_metadata"] = {
["type"] = "zone"
}
}
settag(table.zone, _EcoTag_Tables)
end
return table.zone
-- eco.object.
elseif index == "object" then
if type(value) ~= "table" then
table.object = {
["_metadata"] = {
["type"] = "object"
}
}
settag(table.object, _EcoTag_Tables)
end
return table.object
-- eco.node.
elseif index == "node" then
if type(value) ~= "table" then
table.node = {
["_metadata"] = {
["type"] = "node"
}
}
settag(table.node, _EcoTag_Tables)
end
return table.node
end
end
return nil
end
-- Create table management tags.
settagmethod(_EcoTag_Tables, 'gettable', _EcoGetTableData)
settagmethod(_EcoTag_Main, 'gettable', _EcoManageMainTable)
-- Create the main table and
-- associate it with the tag.
eco = {}
settag(eco, _EcoTag_Main)
-- [[header-stop]] --
-- This is a useful function for
-- iterating through table data.
function print_table(table, prefix)
if prefix == nil then
local metadata = rawget(table, "_metadata");
if type(metadata) == "table" then
prefix = metadata["type"]
else
prefix = ""
end
end
for key, value in table do
if type(value) == "table" then
print_table(value, prefix .. "." .. key)
else
print (prefix .. "." .. key .. "=" .. value)
end
end
end
-- Some example usage.
printf("AREA 1: %0.3f", eco.object[1].area)
printf("AREA 1: %0.3f", eco.object[2].area)
printf("VOLM 1: %0.3f", eco.zone[1].volume)
print("\n=====================================\n\n")
print_table(eco.object[1].node[4])
print("\n=====================================\n\n")
print_table(eco.object[1])
print("\n=====================================\n\n")
print_table(eco.zone[1])