summaryrefslogtreecommitdiff
path: root/libs/assimp/scripts/BlenderImporter/genblenddna.py
diff options
context:
space:
mode:
authorsanine <sanine.not@pm.me>2022-04-16 11:55:09 -0500
committersanine <sanine.not@pm.me>2022-04-16 11:55:09 -0500
commitdb81b925d776103326128bf629cbdda576a223e7 (patch)
tree58bea8155c686733310009f6bed7363f91fbeb9d /libs/assimp/scripts/BlenderImporter/genblenddna.py
parent55860037b14fb3893ba21cf2654c83d349cc1082 (diff)
move 3rd-party librarys into libs/ and add built-in honeysuckle
Diffstat (limited to 'libs/assimp/scripts/BlenderImporter/genblenddna.py')
-rw-r--r--libs/assimp/scripts/BlenderImporter/genblenddna.py299
1 files changed, 299 insertions, 0 deletions
diff --git a/libs/assimp/scripts/BlenderImporter/genblenddna.py b/libs/assimp/scripts/BlenderImporter/genblenddna.py
new file mode 100644
index 0000000..56e1b98
--- /dev/null
+++ b/libs/assimp/scripts/BlenderImporter/genblenddna.py
@@ -0,0 +1,299 @@
+#!/usr/bin/env python3
+# -*- Coding: UTF-8 -*-
+
+# ---------------------------------------------------------------------------
+# Open Asset Import Library (ASSIMP)
+# ---------------------------------------------------------------------------
+#
+# Copyright (c) 2006-2020, ASSIMP Development Team
+#
+# All rights reserved.
+#
+# Redistribution and use of this software in source and binary forms,
+# with or without modification, are permitted provided that the following
+# conditions are met:
+#
+# * Redistributions of source code must retain the above
+# copyright notice, this list of conditions and the
+# following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the
+# following disclaimer in the documentation and/or other
+# materials provided with the distribution.
+#
+# * Neither the name of the ASSIMP team, nor the names of its
+# contributors may be used to endorse or promote products
+# derived from this software without specific prior
+# written permission of the ASSIMP Development Team.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+# ---------------------------------------------------------------------------
+
+"""Generate BlenderSceneGen.h and BlenderScene.cpp from the
+data structures in BlenderScene.h to map from *any* DNA to
+*our* DNA"""
+
+import sys
+import os
+import re
+
+inputfile = os.path.join("..","..","code","BlenderScene.h")
+outputfile_gen = os.path.join("..","..","code","BlenderSceneGen.h")
+outputfile_src = os.path.join("..","..","code","BlenderScene.cpp")
+
+template_gen = "BlenderSceneGen.h.template"
+template_src = "BlenderScene.cpp.template"
+
+# workaround for stackoverflowing when reading the linked list of scene objects
+# with the usual approach. See embedded notes for details.
+Structure_Convert_Base_fullcode = """
+template <> void Structure::Convert<Base>( Base& dest, const FileDatabase& db ) const {
+ // note: as per https://github.com/assimp/assimp/issues/128,
+ // reading the Object linked list recursively is prone to stack overflow.
+ // This structure converter is therefore an hand-written exception that
+ // does it iteratively.
+
+ const int initial_pos = db.reader->GetCurrentPos();
+ std::pair<Base*, int> todo = std::make_pair(&dest, initial_pos);
+ Base* saved_prev = NULL;
+ while(true) {
+ Base& cur_dest = *todo.first;
+ db.reader->SetCurrentPos(todo.second);
+
+ // we know that this is a double-linked, circular list which we never
+ // traverse backwards, so don't bother resolving the back links.
+ cur_dest.prev = NULL;
+
+ ReadFieldPtr<ErrorPolicy_Warn>(cur_dest.object,"*object",db);
+
+ // just record the offset of the blob data and allocate storage.
+ // Does _not_ invoke Convert() recursively.
+ const int old = db.reader->GetCurrentPos();
+
+ // the return value of ReadFieldPtr indicates whether the object
+ // was already cached. In this case, we don't need to resolve
+ // it again.
+ if(!ReadFieldPtr<ErrorPolicy_Warn>(cur_dest.next,"*next",db, true) && cur_dest.next) {
+ todo = std::make_pair(&*cur_dest.next, db.reader->GetCurrentPos());
+ continue;
+ }
+ break;
+ }
+
+ db.reader->SetCurrentPos(initial_pos + size);
+}
+
+"""
+
+
+Structure_Convert_decl = """
+template <> void Structure :: Convert<{a}> (
+ {a}& dest,
+ const FileDatabase& db
+ ) const
+"""
+
+
+Structure_Convert_ptrdecl = """
+ ReadFieldPtr<{policy}>({destcast}dest.{name_canonical},"{name_dna}",db);"""
+
+Structure_Convert_rawptrdecl = """
+ {{
+ boost::shared_ptr<{type}> {name_canonical};
+ ReadFieldPtr<{policy}>({destcast}{name_canonical},"{name_dna}",db);
+ dest.{name_canonical} = {name_canonical}.get();
+ }}"""
+
+Structure_Convert_arraydecl = """
+ ReadFieldArray<{policy}>({destcast}dest.{name_canonical},"{name_dna}",db);"""
+
+Structure_Convert_arraydecl2d = """
+ ReadFieldArray2<{policy}>({destcast}dest.{name_canonical},"{name_dna}",db);"""
+
+Structure_Convert_normal = """
+ ReadField<{policy}>({destcast}dest.{name_canonical},"{name_dna}",db);"""
+
+
+DNA_RegisterConverters_decl = """
+void DNA::RegisterConverters() """
+
+DNA_RegisterConverters_add = """
+ converters["{a}"] = DNA::FactoryPair( &Structure::Allocate<{a}>, &Structure::Convert<{a}> );"""
+
+
+map_policy = {
+ "" : "ErrorPolicy_Igno"
+ ,"IGNO" : "ErrorPolicy_Igno"
+ ,"WARN" : "ErrorPolicy_Warn"
+ ,"FAIL" : "ErrorPolicy_Fail"
+}
+
+#
+def main():
+
+ # -----------------------------------------------------------------------
+ # Parse structure definitions from BlenderScene.h
+ input = open(inputfile,"rt").read()
+
+ #flags = re.ASCII|re.DOTALL|re.MULTILINE
+ flags = re.DOTALL|re.MULTILINE
+ #stripcoms = re.compile(r"/\*(.*?)*\/",flags)
+ getstruct = re.compile(r"struct\s+(\w+?)\s*(:\s*ElemBase)?\s*\{(.*?)^\}\s*;",flags)
+ getsmartx = re.compile(r"(std\s*::\s*)?(vector)\s*<\s*(boost\s*::\s*)?shared_(ptr)\s*<\s*(\w+)\s*>\s*>\s*",flags)
+ getsmartp = re.compile(r"(boost\s*::\s*)?shared_(ptr)\s*<\s*(\w+)\s*>\s*",flags)
+ getrawp = re.compile(r"(\w+)\s*\*\s*",flags)
+ getsmarta = re.compile(r"(std\s*::\s*)?(vector)\s*<\s*(\w+)\s*>\s*",flags)
+ getpolicy = re.compile(r"\s*(WARN|FAIL|IGNO)",flags)
+ stripenum = re.compile(r"enum\s+(\w+)\s*{.*?\}\s*;",flags)
+
+ assert getsmartx and getsmartp and getsmarta and getrawp and getpolicy and stripenum
+
+ enums = set()
+ #re.sub(stripcoms," ",input)
+ #print(input)
+
+ hits = {}
+ while 1:
+ match = re.search(getstruct,input)
+ if match is None:
+ break
+
+ tmp = match.groups()[2]
+ while 1:
+ match2 = re.search(stripenum,tmp)
+ if match2 is None:
+ break
+ tmp = tmp[match2.end():]
+ enums.add(match2.groups()[0])
+
+ hits[match.groups()[0]] = list(
+ filter(lambda x:x[:2] != "//" and len(x),
+ map(str.strip,
+ re.sub(stripenum," ",match.groups()[2]).split(";")
+ )))
+
+ input = input[match.end():]
+
+ for e in enums:
+ print("Enum: "+e)
+ for k,v in hits.items():
+ out = []
+ for line in v:
+
+ policy = "IGNO"
+ py = re.search(getpolicy,line)
+ if not py is None:
+ policy = py.groups()[0]
+ line = re.sub(getpolicy,"",line)
+
+ ty = re.match(getsmartx,line) or re.match(getsmartp,line) or\
+ re.match(getsmarta,line) or re.match(getrawp,line)
+
+ if ty is None:
+ ty = line.split(None,1)[0]
+ else:
+ if len(ty.groups()) == 1:
+ ty = ty.groups()[-1] + "$"
+ elif ty.groups()[1] == "ptr":
+ ty = ty.groups()[2] + "*"
+ elif ty.groups()[1] == "vector":
+ ty = ty.groups()[-1] + ("*" if len(ty.groups()) == 3 else "**")
+ else:
+ assert False
+
+ #print(line)
+ sp = line.split(',')
+ out.append((ty,sp[0].split(None)[-1].strip(),policy))
+ for m in sp[1:]:
+ out.append((ty,m.strip(),policy))
+
+ v[:] = out
+ print("Structure {0}".format(k))
+ for elem in out:
+ print("\t"+"\t".join(elem))
+ print("")
+
+
+ output = open(outputfile_gen,"wt")
+ templt = open(template_gen,"rt").read()
+ s = ""
+
+ # -----------------------------------------------------------------------
+ # Structure::Convert<T> declarations for all supported structures
+ for k,v in hits.items():
+ s += Structure_Convert_decl.format(a=k)+";\n";
+ output.write(templt.replace("<HERE>",s))
+
+ output = open(outputfile_src,"wt")
+ templt = open(template_src,"rt").read()
+ s = ""
+
+ # -----------------------------------------------------------------------
+ # Structure::Convert<T> definitions for all supported structures
+ for k,v in hits.items():
+ s += "//" + "-"*80
+ if k == 'Base':
+ s += Structure_Convert_Base_fullcode
+ continue
+ s += Structure_Convert_decl.format(a=k)+ "{ \n";
+
+ for type, name, policy in v:
+ splits = name.split("[",1)
+ name_canonical = splits[0]
+ #array_part = "" if len(splits)==1 else "["+splits[1]
+ is_raw_ptr = not not type.count("$")
+ ptr_decl = "*"*(type.count("*") + (1 if is_raw_ptr else 0))
+
+ name_dna = ptr_decl+name_canonical #+array_part
+
+ #required = "false"
+ policy = map_policy[policy]
+ destcast = "(int&)" if type in enums else ""
+
+ # POINTER
+ if is_raw_ptr:
+ type = type.replace('$','')
+ s += Structure_Convert_rawptrdecl.format(**locals())
+ elif ptr_decl:
+ s += Structure_Convert_ptrdecl.format(**locals())
+ # ARRAY MEMBER
+ elif name.count('[')==1:
+ s += Structure_Convert_arraydecl.format(**locals())
+ elif name.count('[')==2:
+ s += Structure_Convert_arraydecl2d.format(**locals())
+ # NORMAL MEMBER
+ else:
+ s += Structure_Convert_normal.format(**locals())
+
+ s += "\n\n\tdb.reader->IncPtr(size);\n}\n\n"
+
+
+ # -----------------------------------------------------------------------
+ # DNA::RegisterConverters - collect all available converter functions
+ # in a std::map<name,converter_proc>
+ #s += "#if 0\n"
+ s += "//" + "-"*80 + DNA_RegisterConverters_decl + "{\n"
+ for k,v in hits.items():
+ s += DNA_RegisterConverters_add.format(a=k)
+
+ s += "\n}\n"
+ #s += "#endif\n"
+
+ output.write(templt.replace("<HERE>",s))
+
+ # we got here, so no error
+ return 0
+
+if __name__ == "__main__":
+ sys.exit(main())