From 81fc8a8579432be93f53b25f228007d1d2545609 Mon Sep 17 00:00:00 2001 From: Skye Terran Date: Wed, 25 Aug 2021 13:08:17 -0700 Subject: [PATCH] Encoding works! --- NeutrinoJSONTest.ipynb | 245 ------------------ NeutrinoParseTesting.ipynb | 135 ---------- NeutrinoTestScene.json | 1 - example.neu | 81 ------ python/NeutrinoJSONTest.ipynb | 131 ++++++++++ python/NeutrinoTestScene.json | 1 + python/__pycache__/neutrino.cpython-37.pyc | Bin 0 -> 3520 bytes .../__pycache__/decode.cpython-37.pyc | Bin 0 -> 709 bytes .../__pycache__/encode.cpython-37.pyc | Bin 0 -> 3527 bytes python/neutrino/decode.py | 30 +++ python/neutrino/encode.py | 189 ++++++++++++++ 11 files changed, 351 insertions(+), 462 deletions(-) delete mode 100644 NeutrinoJSONTest.ipynb delete mode 100644 NeutrinoParseTesting.ipynb delete mode 100644 NeutrinoTestScene.json delete mode 100644 example.neu create mode 100644 python/NeutrinoJSONTest.ipynb create mode 100644 python/NeutrinoTestScene.json create mode 100644 python/__pycache__/neutrino.cpython-37.pyc create mode 100644 python/neutrino/__pycache__/decode.cpython-37.pyc create mode 100644 python/neutrino/__pycache__/encode.cpython-37.pyc create mode 100644 python/neutrino/decode.py create mode 100644 python/neutrino/encode.py diff --git a/NeutrinoJSONTest.ipynb b/NeutrinoJSONTest.ipynb deleted file mode 100644 index 115d213..0000000 --- a/NeutrinoJSONTest.ipynb +++ /dev/null @@ -1,245 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 217, - "source": [ - "import json\r\n", - "\r\n", - "# create a new scene graph\r\n", - "def new_scene(name):\r\n", - " # create empty neutrino data\r\n", - " data = {\r\n", - " \"meta\": {\r\n", - " \"name\": (\"name\", name),\r\n", - " \"scale\": (\"float\", 1.0),\r\n", - " \"asset_path\": (\"path\", \"./\"),\r\n", - " },\r\n", - " \"graph\": {\r\n", - " \"scene\": {},\r\n", - " \"assets\": {}\r\n", - " },\r\n", - " \"internal\": {\r\n", - " \"max_object_key\": {\"index\": 0},\r\n", - " \"max_cache_key\": {\"index\": 0}\r\n", - " }\r\n", - " }\r\n", - "\r\n", - " # return that empty data\r\n", - " return data\r\n", - "\r\n", - "# write the data to a JSON file\r\n", - "def save_scene(data, readable):\r\n", - " # create working copy of the scene data\r\n", - " clean_data = data.copy()\r\n", - "\r\n", - " # get rid of internal data (not to be exported)\r\n", - " del clean_data[\"internal\"]\r\n", - " \r\n", - " filename = data[\"meta\"][\"name\"][1].replace(\" \", \"\") + \".json\"\r\n", - " with open(filename, \"w\") as outfile:\r\n", - " if readable:\r\n", - " json.dump(clean_data, outfile, indent = 4)\r\n", - " else:\r\n", - " json.dump(clean_data, outfile)\r\n", - "\r\n", - "# get a new indexed object key and track it\r\n", - "def new_key(index):\r\n", - " # get the indexed key\r\n", - " key = hex(index[\"index\"] + 1)\r\n", - "\r\n", - " # index the max key\r\n", - " index[\"index\"] += 1\r\n", - "\r\n", - " return key\r\n", - "\r\n", - "# add an asset to the graph\r\n", - "def add_asset(data, name, path):\r\n", - " asset_data = {\r\n", - " \"name\": (\"name\", name),\r\n", - " \"file\": (\"path\", path)\r\n", - " }\r\n", - " \r\n", - " # add the asset to the graph\r\n", - " data[\"graph\"][\"assets\"][new_key(data[\"internal\"][\"max_object_key\"])] = (\"asset\", asset_data)\r\n", - "\r\n", - "# add an object to the scene\r\n", - "def spawn_object(data, name, asset):\r\n", - " object_data = {\r\n", - " \"name\": (\"name\", name),\r\n", - " \"asset\": \"\",\r\n", - " \"trans\": (\"trans\", {\r\n", - " \"position\": (\"vec3\", [0.0, 0.0, 0.0]),\r\n", - " \"rotation\": (\"vec3\", [0.0, 0.0, 0.0]),\r\n", - " \"scale\": (\"vec3\", [1.0, 1.0, 1.0])\r\n", - " })\r\n", - " }\r\n", - "\r\n", - " # get an asset key by the provided name\r\n", - " for key, value in data[\"graph\"][\"assets\"].items():\r\n", - " if value[1][\"name\"][1] == asset:\r\n", - " object_data[\"asset\"] = f\"*{key}\"\r\n", - "\r\n", - " # add the object to the scene\r\n", - " data[\"graph\"][\"scene\"][new_key(data[\"internal\"][\"max_object_key\"])] = (\"object\", object_data)" - ], - "outputs": [], - "metadata": {} - }, - { - "cell_type": "markdown", - "source": [ - "### Implement SPORC for storage/memory optimization\r\n", - "(Single-Pointer Objective Relational Cache)" - ], - "metadata": {} - }, - { - "cell_type": "code", - "execution_count": 218, - "source": [ - "# recursively cache a single typeval tuple object\r\n", - "def cache_typeval(cache, typeval):\r\n", - " # ignore if not typeval\r\n", - " if type(typeval) == tuple:\r\n", - " for key, value in typeval[1].items():\r\n", - " # refuse to cache pointers (that's just... that would just be a nightmare)\r\n", - " if type(value) == str:\r\n", - " is_pointer = (\"*\" in value)\r\n", - " else:\r\n", - " is_pointer = False\r\n", - " if not is_pointer:\r\n", - " # cache member objects if it's a dictionary object\r\n", - " if type(value[1]) == dict:\r\n", - " cache_typeval(cache, value)\r\n", - "\r\n", - " value_hash = hash(str(value))\r\n", - "\r\n", - " # track in cache\r\n", - " if value_hash not in cache[\"objects\"]:\r\n", - " cache_pointer = new_key(cache[\"key_index\"])\r\n", - " cache[\"objects\"][value_hash] = {\"key\": cache_pointer, \"value\": value, \"count\": 1}\r\n", - " else:\r\n", - " cache_pointer = cache[\"objects\"][value_hash][\"key\"]\r\n", - " cache[\"objects\"][value_hash][\"count\"] += 1\r\n", - "\r\n", - " # replace real value with hash\r\n", - " typeval[1][key] = \"#\" + cache_pointer\r\n", - "\r\n", - "# if there's only one instance of a certain value, convert it back to the original value and destroy the cached version\r\n", - "def uncache_typeval(cache, typeval):\r\n", - " for key, value in typeval[1].items():\r\n", - " # refuse to cache pointers (that's just... that would just be a nightmare)\r\n", - " if type(value) == str:\r\n", - " is_pointer = (\"*\" in value)\r\n", - " else:\r\n", - " is_pointer = False\r\n", - " if not is_pointer:\r\n", - " # cache member objects if it's a dictionary object\r\n", - " if type(value[1]) == dict:\r\n", - " uncache_typeval(cache, value)\r\n", - "\r\n", - " value_hash = hash(str(value))\r\n", - "\r\n", - " # check if it occurs only once\r\n", - " cache_key = value.replace(\"#\", \"\")\r\n", - " if cache[cache_key][\"count\"] <= 1:\r\n", - " # replace the cache pointer in the scene data with its original value\r\n", - " typeval[1][key] = cache[cache_key][\"value\"]\r\n", - "\r\n", - " # delete this object from the cache\r\n", - " del cache[cache_key]\r\n", - "\r\n", - "# cache the scene\r\n", - "def cache_scene(data):\r\n", - " # add the cache object to the scene data\r\n", - " data[\"cache\"] = {}\r\n", - "\r\n", - " containers = [\r\n", - " data[\"graph\"][\"scene\"],\r\n", - " data[\"graph\"][\"assets\"]\r\n", - " ]\r\n", - "\r\n", - " # build a cache of value hashes and pointers\r\n", - " hash_cache = {\"key_index\": {\"index\": 0}, \"objects\": {}}\r\n", - " for objects in containers:\r\n", - " for key, value in objects.items():\r\n", - " cache_typeval(hash_cache, value)\r\n", - "\r\n", - " # create a cache hashed with pointer keys instead of value hashes\r\n", - " key_cache = {}\r\n", - " for key, value in hash_cache[\"objects\"].items():\r\n", - " key_cache[value[\"key\"]] = {\"value\": value[\"value\"], \"count\": value[\"count\"]}\r\n", - "\r\n", - " # prune the cache to only redirect repeat values\r\n", - " for objects in containers:\r\n", - " for key, value in objects.items():\r\n", - " uncache_typeval(key_cache, value)\r\n", - "\r\n", - " # create a serialized cache usable by neutrino\r\n", - " serial_cache = {}\r\n", - " for key, value in key_cache.items():\r\n", - " serial_cache[key] = value[\"value\"]\r\n", - "\r\n", - " # add that cache to the neutrino scene data\r\n", - " data[\"cache\"] = serial_cache" - ], - "outputs": [], - "metadata": {} - }, - { - "cell_type": "code", - "execution_count": 219, - "source": [ - "# just returns a random string\r\n", - "import random\r\n", - "import string\r\n", - "def random_string(length):\r\n", - " return ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(length))\r\n", - "\r\n", - "# create test scene\r\n", - "test_scene = new_scene(\"Neutrino Test Scene\")\r\n", - "\r\n", - "# populate assets\r\n", - "asset_names = []\r\n", - "for i in range(10):\r\n", - " name = random_string(8)\r\n", - " add_asset(test_scene, name, \"Assets/TestAsset.obj\")\r\n", - " asset_names.append(name)\r\n", - "\r\n", - "# populate objects in scene\r\n", - "for i in range(50):\r\n", - " spawn_object(test_scene, random_string(8), random.choice(asset_names))\r\n", - "\r\n", - "cache_scene(test_scene)\r\n", - "save_scene(test_scene, False)" - ], - "outputs": [], - "metadata": {} - } - ], - "metadata": { - "orig_nbformat": 4, - "language_info": { - "name": "python", - "version": "3.7.8", - "mimetype": "text/x-python", - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "pygments_lexer": "ipython3", - "nbconvert_exporter": "python", - "file_extension": ".py" - }, - "kernelspec": { - "name": "python3", - "display_name": "Python 3.7.8 64-bit" - }, - "interpreter": { - "hash": "57baa5815c940fdaff4d14510622de9616cae602444507ba5d0b6727c008cbd6" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} \ No newline at end of file diff --git a/NeutrinoParseTesting.ipynb b/NeutrinoParseTesting.ipynb deleted file mode 100644 index 0c14b65..0000000 --- a/NeutrinoParseTesting.ipynb +++ /dev/null @@ -1,135 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 86, - "source": [ - "file = open(\"testB.neu\")\r\n", - "dirty_blob = file.read()\r\n", - "\r\n", - "# get rid of comments and leading/trailing whitespace\r\n", - "lines = dirty_blob.split(\"\\n\")\r\n", - "for i, line in enumerate(lines):\r\n", - " if line.strip()[:2] == \"//\":\r\n", - " del lines[i]\r\n", - "\r\n", - "for i, line in enumerate(lines):\r\n", - " lines[i] = line.strip()\r\n", - "\r\n", - "tidy_blob = \" \".join(lines)" - ], - "outputs": [], - "metadata": {} - }, - { - "cell_type": "code", - "execution_count": 87, - "source": [ - "data = []\r\n", - "\r\n", - "# get blocks\r\n", - "for line in lines:\r\n", - " object = {}\r\n", - " if \"=\" in line:\r\n", - " keytype = line.split(\" \")[0].split(\":\")\r\n", - " key = keytype[0]\r\n", - " object[\"key\"] = key\r\n", - " if len(keytype) > 1:\r\n", - " type = keytype[1]\r\n", - " object[\"type\"] = type\r\n", - " data.append(object)" - ], - "outputs": [], - "metadata": {} - }, - { - "cell_type": "code", - "execution_count": 88, - "source": [ - "words = tidy_blob.split(\" \")" - ], - "outputs": [], - "metadata": {} - }, - { - "cell_type": "code", - "execution_count": 89, - "source": [ - "def extract_objects(keywords):\r\n", - " blocks = []\r\n", - " depth = -1\r\n", - " i = -1\r\n", - " last = \"\"\r\n", - " for word in keywords:\r\n", - " #print(f\"Word: {word} | Depth: {depth} | i: {i}\")\r\n", - " if word == \"{\":\r\n", - " depth += 1\r\n", - " if depth == 1:\r\n", - " #print(\"New block of depth 1\")\r\n", - " blocks.append({\"key\": last, \"object\": []})\r\n", - " i += 1\r\n", - " elif word == \"}\":\r\n", - " depth -= 1\r\n", - " else:\r\n", - " last = word\r\n", - " if depth >= 1:\r\n", - " blocks[i][\"object\"].append(word)\r\n", - " return blocks\r\n", - "\r\n", - "data = extract_objects(words)\r\n", - "temp = []\r\n", - "for blob in data:\r\n", - " temp.append(extract_objects(blob[\"object\"]))\r\n", - "\r\n", - " \r\n", - "\r\n", - "temp" - ], - "outputs": [ - { - "output_type": "execute_result", - "data": { - "text/plain": [ - "[[{'key': 'aa', 'object': ['{', 'aaa']},\n", - " {'key': 'ab', 'object': ['{', 'aba']},\n", - " {'key': 'ac', 'object': ['{', 'abb']}],\n", - " [{'key': 'ba', 'object': ['{']},\n", - " {'key': 'bb', 'object': ['{']},\n", - " {'key': 'bc', 'object': ['{']}],\n", - " [{'key': 'ba', 'object': ['{']},\n", - " {'key': 'bb', 'object': ['{']},\n", - " {'key': 'bc', 'object': ['{']}]]" - ] - }, - "metadata": {}, - "execution_count": 89 - } - ], - "metadata": {} - } - ], - "metadata": { - "orig_nbformat": 4, - "language_info": { - "name": "python", - "version": "3.7.8", - "mimetype": "text/x-python", - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "pygments_lexer": "ipython3", - "nbconvert_exporter": "python", - "file_extension": ".py" - }, - "kernelspec": { - "name": "python3", - "display_name": "Python 3.7.8 64-bit" - }, - "interpreter": { - "hash": "57baa5815c940fdaff4d14510622de9616cae602444507ba5d0b6727c008cbd6" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} \ No newline at end of file diff --git a/NeutrinoTestScene.json b/NeutrinoTestScene.json deleted file mode 100644 index ec593ff..0000000 --- a/NeutrinoTestScene.json +++ /dev/null @@ -1 +0,0 @@ -{"meta": {"name": ["name", "Neutrino Test Scene"], "scale": ["float", 1.0], "asset_path": ["path", "./"]}, "graph": {"scene": {"0xb": ["object", {"name": ["name", "K8ZWNOQD"], "asset": "*0x7", "trans": "#0x4"}], "0xc": ["object", {"name": ["name", "US0DHKXM"], "asset": "*0x2", "trans": "#0x4"}], "0xd": ["object", {"name": ["name", "DZ53QE47"], "asset": "*0x7", "trans": "#0x4"}], "0xe": ["object", {"name": ["name", "L0MLPJ07"], "asset": "*0x9", "trans": "#0x4"}], "0xf": ["object", {"name": ["name", "RHAQ5Y6Y"], "asset": "*0x3", "trans": "#0x4"}], "0x10": ["object", {"name": ["name", "70EO9E5L"], "asset": "*0x9", "trans": "#0x4"}], "0x11": ["object", {"name": ["name", "V7QSXNME"], "asset": "*0x8", "trans": "#0x4"}], "0x12": ["object", {"name": ["name", "F60CAXPY"], "asset": "*0xa", "trans": "#0x4"}], "0x13": ["object", {"name": ["name", "FBOCRYEU"], "asset": "*0x5", "trans": "#0x4"}], "0x14": ["object", {"name": ["name", "BU7FDZ8X"], "asset": "*0x9", "trans": "#0x4"}], "0x15": ["object", {"name": ["name", "6J5HMTF0"], "asset": "*0x6", "trans": "#0x4"}], "0x16": ["object", {"name": ["name", "GWNR7BVP"], "asset": "*0xa", "trans": "#0x4"}], "0x17": ["object", {"name": ["name", "3L6PXJMP"], "asset": "*0x3", "trans": "#0x4"}], "0x18": ["object", {"name": ["name", "GFQ1ND0L"], "asset": "*0x5", "trans": "#0x4"}], "0x19": ["object", {"name": ["name", "TJOVYREC"], "asset": "*0x6", "trans": "#0x4"}], "0x1a": ["object", {"name": ["name", "8APBDYNQ"], "asset": "*0x2", "trans": "#0x4"}], "0x1b": ["object", {"name": ["name", "QEBU36A0"], "asset": "*0x3", "trans": "#0x4"}], "0x1c": ["object", {"name": ["name", "E2DONFRV"], "asset": "*0x8", "trans": "#0x4"}], "0x1d": ["object", {"name": ["name", "K266KMAB"], "asset": "*0x6", "trans": "#0x4"}], "0x1e": ["object", {"name": ["name", "YDW0I1J5"], "asset": "*0xa", "trans": "#0x4"}], "0x1f": ["object", {"name": ["name", "0CKXOWCH"], "asset": "*0x8", "trans": "#0x4"}], "0x20": ["object", {"name": ["name", "5ETNQA9W"], "asset": "*0x6", "trans": "#0x4"}], "0x21": ["object", {"name": ["name", "9OE70GMX"], "asset": "*0x1", "trans": "#0x4"}], "0x22": ["object", {"name": ["name", "R90HUM0L"], "asset": "*0x1", "trans": "#0x4"}], "0x23": ["object", {"name": ["name", "MZY8N9IZ"], "asset": "*0x6", "trans": "#0x4"}], "0x24": ["object", {"name": ["name", "NLFWVF6B"], "asset": "*0x1", "trans": "#0x4"}], "0x25": ["object", {"name": ["name", "6BA2464B"], "asset": "*0x6", "trans": "#0x4"}], "0x26": ["object", {"name": ["name", "7LNCT9LH"], "asset": "*0x3", "trans": "#0x4"}], "0x27": ["object", {"name": ["name", "A1R1LT89"], "asset": "*0xa", "trans": "#0x4"}], "0x28": ["object", {"name": ["name", "89ZWAJ9G"], "asset": "*0x1", "trans": "#0x4"}], "0x29": ["object", {"name": ["name", "IRB764Q6"], "asset": "*0x4", "trans": "#0x4"}], "0x2a": ["object", {"name": ["name", "PBR36UOB"], "asset": "*0x6", "trans": "#0x4"}], "0x2b": ["object", {"name": ["name", "I8FT701J"], "asset": "*0x7", "trans": "#0x4"}], "0x2c": ["object", {"name": ["name", "1I637ECH"], "asset": "*0x2", "trans": "#0x4"}], "0x2d": ["object", {"name": ["name", "A6UDB97O"], "asset": "*0x8", "trans": "#0x4"}], "0x2e": ["object", {"name": ["name", "0M9RLFDZ"], "asset": "*0x6", "trans": "#0x4"}], "0x2f": ["object", {"name": ["name", "IXTLUU20"], "asset": "*0x7", "trans": "#0x4"}], "0x30": ["object", {"name": ["name", "D3SL2R4M"], "asset": "*0x9", "trans": "#0x4"}], "0x31": ["object", {"name": ["name", "CIIS6Y6K"], "asset": "*0x8", "trans": "#0x4"}], "0x32": ["object", {"name": ["name", "M1XFZQJZ"], "asset": "*0xa", "trans": "#0x4"}], "0x33": ["object", {"name": ["name", "W699N3Y5"], "asset": "*0xa", "trans": "#0x4"}], "0x34": ["object", {"name": ["name", "MK4XICU6"], "asset": "*0x7", "trans": "#0x4"}], "0x35": ["object", {"name": ["name", "JH5PLU6Q"], "asset": "*0x7", "trans": "#0x4"}], "0x36": ["object", {"name": ["name", "IIUCHG2G"], "asset": "*0x4", "trans": "#0x4"}], "0x37": ["object", {"name": ["name", "Q4GXK1K4"], "asset": "*0x2", "trans": "#0x4"}], "0x38": ["object", {"name": ["name", "S623ETE1"], "asset": "*0x1", "trans": "#0x4"}], "0x39": ["object", {"name": ["name", "2065J1LS"], "asset": "*0x5", "trans": "#0x4"}], "0x3a": ["object", {"name": ["name", "ZTNA2RLO"], "asset": "*0xa", "trans": "#0x4"}], "0x3b": ["object", {"name": ["name", "SDC5B3QK"], "asset": "*0x3", "trans": "#0x4"}], "0x3c": ["object", {"name": ["name", "EGIL6IC4"], "asset": "*0x7", "trans": "#0x4"}]}, "assets": {"0x1": ["asset", {"name": ["name", "C2FK95T4"], "file": "#0x37"}], "0x2": ["asset", {"name": ["name", "L4UBCTM0"], "file": "#0x37"}], "0x3": ["asset", {"name": ["name", "JLV3H133"], "file": "#0x37"}], "0x4": ["asset", {"name": ["name", "KW5P72ZQ"], "file": "#0x37"}], "0x5": ["asset", {"name": ["name", "VMPY9TWY"], "file": "#0x37"}], "0x6": ["asset", {"name": ["name", "5UI4DUPF"], "file": "#0x37"}], "0x7": ["asset", {"name": ["name", "F9HV6WMM"], "file": "#0x37"}], "0x8": ["asset", {"name": ["name", "GUH5P1MT"], "file": "#0x37"}], "0x9": ["asset", {"name": ["name", "CMJT9GHT"], "file": "#0x37"}], "0xa": ["asset", {"name": ["name", "L0QXBOVT"], "file": "#0x37"}]}}, "cache": {"0x2": ["vec3", [0.0, 0.0, 0.0]], "0x3": ["vec3", [1.0, 1.0, 1.0]], "0x4": ["trans", {"position": "#0x2", "rotation": "#0x2", "scale": "#0x3"}], "0x37": ["path", "Assets/TestAsset.obj"]}} \ No newline at end of file diff --git a/example.neu b/example.neu deleted file mode 100644 index 26ee756..0000000 --- a/example.neu +++ /dev/null @@ -1,81 +0,0 @@ -// & declares a key pointing to object instantiated by that declaration (in this case, we're using integers in hex) -// keys are NOT indices - ultimately they should be ingested as keys to a dictionary containing each object in the Neutrino file -// * gets a reference to a key's object (Neutrino will try to preserve this reference in the target software whenever possible) -// # gets a copy from a cached object's key (Neutrino will simply replace this reference with a copy of its value - this is simply to consolidate repetitive data in-exchange) - -// overall structure: -/* -meta = {}, -graph = { - scene = {}, - assets = {} -}, -cache = {} -*/ - -meta = { - // -}, -graph = { - // note - "scene" and "assets" are essentially namespaces - // the scene itself - scene = { - &0: object = { - name: string = "SM_LargeWindow_A", - mesh: mesh = *2, - transform: trans = #b - }, - &1: object = { - name: string = "SM_LargeWindow_A2", - mesh: mesh = *2, - transform: trans = #b - } - }, - // assets used by the scene - assets { - &2: mesh { - source: path = "/Assets/Props/LargeWindowA.obj", - materials: [mat] = [*4] - }, - &4: mat { - name: string = "Simple Glass", - parent: shader = *7, - // "shader.props" is a subtype of the "shader" type, which is just a namespace that keeps it from being mixed up with other "props" subtypes (like "mesh.props", etc.) - parameters: shader.props = { - albedo: tex = *6, - roughness: float = 0.15, - normal: vec4 = #a - } - }, - &5: mat { - name: string = "Blockout Grey", - parent: shader = *7, - parameters: shader.props = { - albedo: vec4 = (0.5, 0.5, 0.5, 1.0), - roughness: float = 0.85, - normal: vec4 = #a - } - }, - &6: tex { - source: path = "/Assets/Textures/T_WindowGrime.png" - }, - &7: shader { - source: path = "/Assets/Shaders/PBRBasic.wgsl" - } - }, -}, -// anonymous objects shared by multiple other objects -cache { - // this vector is common as a position or rotation value - &8: vec3 = (0.0, 0.0, 0.0), - // this vector is common as a scale value - &9: vec3 = (1.0, 1.0, 1.0), - // this vector is common as a normal value - &a: vec4 = (0.5, 0.5, 1.0, 1.0), - // this transform is common because it's the default - &b: trans = { - position: vec3 = #8, - rotation: vec3 = #8, - scale: vec3 = #9 - } -} \ No newline at end of file diff --git a/python/NeutrinoJSONTest.ipynb b/python/NeutrinoJSONTest.ipynb new file mode 100644 index 0000000..d450c0a --- /dev/null +++ b/python/NeutrinoJSONTest.ipynb @@ -0,0 +1,131 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "source": [ + "# just returns a random string\r\n", + "import random\r\n", + "import string\r\n", + "from neutrino.encode import *\r\n", + "def random_string(length):\r\n", + " return ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(length))\r\n", + "\r\n", + "# create test scene\r\n", + "test_scene = new_scene(name = \"Neutrino Test Scene\", cache = True)\r\n", + "\r\n", + "# populate assets\r\n", + "asset_names = []\r\n", + "for i in range(10):\r\n", + " name = random_string(8)\r\n", + " add_asset(test_scene, name, \"Assets/TestAsset.obj\")\r\n", + " asset_names.append(name)\r\n", + "\r\n", + "# populate objects in scene\r\n", + "for i in range(50):\r\n", + " spawn_object(test_scene, random_string(8), random.choice(asset_names))\r\n", + "\r\n", + "save_scene(test_scene, False)" + ], + "outputs": [], + "metadata": {} + }, + { + "cell_type": "code", + "execution_count": 2, + "source": [ + "import json\r\n", + "from neutrino.decode import *\r\n", + "\r\n", + "imported_data = json.load(open(\"NeutrinoTestScene.json\"))\r\n", + "\r\n", + "for key, value in imported_data[\"graph\"][\"scene\"].items():\r\n", + " value = (imported_data[\"cache\"][\"names\"][value[0][1:]], value[1])\r\n", + " print(value)" + ], + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "['@0xa', {'@0x1': ['@0x1', 'OBK1NYBK'], '@0x4': '*0x9', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', 'KXKKGWH1'], '@0x4': '*0x1', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', 'FP8K8N8K'], '@0x4': '*0x7', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', 'MOGF2L64'], '@0x4': '*0x1', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', 'Z8EFSXJH'], '@0x4': '*0x8', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', '1ZMPRUS6'], '@0x4': '*0x5', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', 'QVQSXH1U'], '@0x4': '*0x5', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', 'Q0F9YKF3'], '@0x4': '*0x2', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', 'RS1HURTI'], '@0x4': '*0x3', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', '9IT2UDE7'], '@0x4': '*0x2', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', 'JJZ9VA2P'], '@0x4': '*0x3', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', 'PE6Y5NBE'], '@0x4': '*0x5', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', '41VJPUWO'], '@0x4': '*0x2', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', '3D63B4QE'], '@0x4': '*0x4', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', '5JZIUIZ9'], '@0x4': '*0x6', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', 'ZD6DD8E1'], '@0x4': '*0x1', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', 'MIRYB8QW'], '@0x4': '*0x3', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', '9HEY01NR'], '@0x4': '*0xa', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', '3EK2Y8LS'], '@0x4': '*0x4', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', 'KJYNHF9B'], '@0x4': '*0x8', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', '1WUOY60X'], '@0x4': '*0x5', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', 'W2L3HTUI'], '@0x4': '*0x2', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', 'K4L6USDR'], '@0x4': '*0x6', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', 'ZF5RNV1N'], '@0x4': '*0x1', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', '62KC64SW'], '@0x4': '*0x7', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', '1QCUVQII'], '@0x4': '*0x8', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', '0IVRI09E'], '@0x4': '*0x3', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', 'J8J492ET'], '@0x4': '*0x9', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', 'MJJTBO2L'], '@0x4': '*0xa', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', '5QAA9XJZ'], '@0x4': '*0x6', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', '21GNFNFG'], '@0x4': '*0x7', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', '132YJS72'], '@0x4': '*0x5', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', 'E7GT5ZZ0'], '@0x4': '*0x1', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', '26DIERE1'], '@0x4': '*0x2', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', 'KTSB2GMU'], '@0x4': '*0x4', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', 'ETRS6ZK2'], '@0x4': '*0x2', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', '8X2ZYUGQ'], '@0x4': '*0x5', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', 'L09LNFXL'], '@0x4': '*0x4', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', '4MHVZCEE'], '@0x4': '*0x7', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', 'YV5R9UAL'], '@0x4': '*0x6', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', '0BRGWQ75'], '@0x4': '*0x6', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', 'W53N74LW'], '@0x4': '*0xa', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', 'S1PLWUWH'], '@0x4': '*0x1', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', 'I7GJKHL6'], '@0x4': '*0x8', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', 'IPZGY627'], '@0x4': '*0xa', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', '3LAE7CYV'], '@0x4': '*0x8', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', 'SUPYOPZB'], '@0x4': '*0x7', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', '2TSTYW4P'], '@0x4': '*0xa', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', 'E47HYX2O'], '@0x4': '*0x1', '@0x5': '#0x4'}]\n", + "['@0xa', {'@0x1': ['@0x1', 'KE36JYS7'], '@0x4': '*0x2', '@0x5': '#0x4'}]\n" + ] + } + ], + "metadata": {} + } + ], + "metadata": { + "orig_nbformat": 4, + "language_info": { + "name": "python", + "version": "3.7.8", + "mimetype": "text/x-python", + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "pygments_lexer": "ipython3", + "nbconvert_exporter": "python", + "file_extension": ".py" + }, + "kernelspec": { + "name": "python3", + "display_name": "Python 3.7.8 64-bit" + }, + "interpreter": { + "hash": "57baa5815c940fdaff4d14510622de9616cae602444507ba5d0b6727c008cbd6" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} \ No newline at end of file diff --git a/python/NeutrinoTestScene.json b/python/NeutrinoTestScene.json new file mode 100644 index 0000000..479e6c5 --- /dev/null +++ b/python/NeutrinoTestScene.json @@ -0,0 +1 @@ +{"meta": {"name": ["name", "Neutrino Test Scene"], "scale": ["float", 1.0], "asset_path": ["path", "./"]}, "graph": {"scene": {"0xb": ["@0xa", {"@0x1": ["@0x1", "OBK1NYBK"], "@0x4": "*0x9", "@0x5": "#0x4"}], "0xc": ["@0xa", {"@0x1": ["@0x1", "KXKKGWH1"], "@0x4": "*0x1", "@0x5": "#0x4"}], "0xd": ["@0xa", {"@0x1": ["@0x1", "FP8K8N8K"], "@0x4": "*0x7", "@0x5": "#0x4"}], "0xe": ["@0xa", {"@0x1": ["@0x1", "MOGF2L64"], "@0x4": "*0x1", "@0x5": "#0x4"}], "0xf": ["@0xa", {"@0x1": ["@0x1", "Z8EFSXJH"], "@0x4": "*0x8", "@0x5": "#0x4"}], "0x10": ["@0xa", {"@0x1": ["@0x1", "1ZMPRUS6"], "@0x4": "*0x5", "@0x5": "#0x4"}], "0x11": ["@0xa", {"@0x1": ["@0x1", "QVQSXH1U"], "@0x4": "*0x5", "@0x5": "#0x4"}], "0x12": ["@0xa", {"@0x1": ["@0x1", "Q0F9YKF3"], "@0x4": "*0x2", "@0x5": "#0x4"}], "0x13": ["@0xa", {"@0x1": ["@0x1", "RS1HURTI"], "@0x4": "*0x3", "@0x5": "#0x4"}], "0x14": ["@0xa", {"@0x1": ["@0x1", "9IT2UDE7"], "@0x4": "*0x2", "@0x5": "#0x4"}], "0x15": ["@0xa", {"@0x1": ["@0x1", "JJZ9VA2P"], "@0x4": "*0x3", "@0x5": "#0x4"}], "0x16": ["@0xa", {"@0x1": ["@0x1", "PE6Y5NBE"], "@0x4": "*0x5", "@0x5": "#0x4"}], "0x17": ["@0xa", {"@0x1": ["@0x1", "41VJPUWO"], "@0x4": "*0x2", "@0x5": "#0x4"}], "0x18": ["@0xa", {"@0x1": ["@0x1", "3D63B4QE"], "@0x4": "*0x4", "@0x5": "#0x4"}], "0x19": ["@0xa", {"@0x1": ["@0x1", "5JZIUIZ9"], "@0x4": "*0x6", "@0x5": "#0x4"}], "0x1a": ["@0xa", {"@0x1": ["@0x1", "ZD6DD8E1"], "@0x4": "*0x1", "@0x5": "#0x4"}], "0x1b": ["@0xa", {"@0x1": ["@0x1", "MIRYB8QW"], "@0x4": "*0x3", "@0x5": "#0x4"}], "0x1c": ["@0xa", {"@0x1": ["@0x1", "9HEY01NR"], "@0x4": "*0xa", "@0x5": "#0x4"}], "0x1d": ["@0xa", {"@0x1": ["@0x1", "3EK2Y8LS"], "@0x4": "*0x4", "@0x5": "#0x4"}], "0x1e": ["@0xa", {"@0x1": ["@0x1", "KJYNHF9B"], "@0x4": "*0x8", "@0x5": "#0x4"}], "0x1f": ["@0xa", {"@0x1": ["@0x1", "1WUOY60X"], "@0x4": "*0x5", "@0x5": "#0x4"}], "0x20": ["@0xa", {"@0x1": ["@0x1", "W2L3HTUI"], "@0x4": "*0x2", "@0x5": "#0x4"}], "0x21": ["@0xa", {"@0x1": ["@0x1", "K4L6USDR"], "@0x4": "*0x6", "@0x5": "#0x4"}], "0x22": ["@0xa", {"@0x1": ["@0x1", "ZF5RNV1N"], "@0x4": "*0x1", "@0x5": "#0x4"}], "0x23": ["@0xa", {"@0x1": ["@0x1", "62KC64SW"], "@0x4": "*0x7", "@0x5": "#0x4"}], "0x24": ["@0xa", {"@0x1": ["@0x1", "1QCUVQII"], "@0x4": "*0x8", "@0x5": "#0x4"}], "0x25": ["@0xa", {"@0x1": ["@0x1", "0IVRI09E"], "@0x4": "*0x3", "@0x5": "#0x4"}], "0x26": ["@0xa", {"@0x1": ["@0x1", "J8J492ET"], "@0x4": "*0x9", "@0x5": "#0x4"}], "0x27": ["@0xa", {"@0x1": ["@0x1", "MJJTBO2L"], "@0x4": "*0xa", "@0x5": "#0x4"}], "0x28": ["@0xa", {"@0x1": ["@0x1", "5QAA9XJZ"], "@0x4": "*0x6", "@0x5": "#0x4"}], "0x29": ["@0xa", {"@0x1": ["@0x1", "21GNFNFG"], "@0x4": "*0x7", "@0x5": "#0x4"}], "0x2a": ["@0xa", {"@0x1": ["@0x1", "132YJS72"], "@0x4": "*0x5", "@0x5": "#0x4"}], "0x2b": ["@0xa", {"@0x1": ["@0x1", "E7GT5ZZ0"], "@0x4": "*0x1", "@0x5": "#0x4"}], "0x2c": ["@0xa", {"@0x1": ["@0x1", "26DIERE1"], "@0x4": "*0x2", "@0x5": "#0x4"}], "0x2d": ["@0xa", {"@0x1": ["@0x1", "KTSB2GMU"], "@0x4": "*0x4", "@0x5": "#0x4"}], "0x2e": ["@0xa", {"@0x1": ["@0x1", "ETRS6ZK2"], "@0x4": "*0x2", "@0x5": "#0x4"}], "0x2f": ["@0xa", {"@0x1": ["@0x1", "8X2ZYUGQ"], "@0x4": "*0x5", "@0x5": "#0x4"}], "0x30": ["@0xa", {"@0x1": ["@0x1", "L09LNFXL"], "@0x4": "*0x4", "@0x5": "#0x4"}], "0x31": ["@0xa", {"@0x1": ["@0x1", "4MHVZCEE"], "@0x4": "*0x7", "@0x5": "#0x4"}], "0x32": ["@0xa", {"@0x1": ["@0x1", "YV5R9UAL"], "@0x4": "*0x6", "@0x5": "#0x4"}], "0x33": ["@0xa", {"@0x1": ["@0x1", "0BRGWQ75"], "@0x4": "*0x6", "@0x5": "#0x4"}], "0x34": ["@0xa", {"@0x1": ["@0x1", "W53N74LW"], "@0x4": "*0xa", "@0x5": "#0x4"}], "0x35": ["@0xa", {"@0x1": ["@0x1", "S1PLWUWH"], "@0x4": "*0x1", "@0x5": "#0x4"}], "0x36": ["@0xa", {"@0x1": ["@0x1", "I7GJKHL6"], "@0x4": "*0x8", "@0x5": "#0x4"}], "0x37": ["@0xa", {"@0x1": ["@0x1", "IPZGY627"], "@0x4": "*0xa", "@0x5": "#0x4"}], "0x38": ["@0xa", {"@0x1": ["@0x1", "3LAE7CYV"], "@0x4": "*0x8", "@0x5": "#0x4"}], "0x39": ["@0xa", {"@0x1": ["@0x1", "SUPYOPZB"], "@0x4": "*0x7", "@0x5": "#0x4"}], "0x3a": ["@0xa", {"@0x1": ["@0x1", "2TSTYW4P"], "@0x4": "*0xa", "@0x5": "#0x4"}], "0x3b": ["@0xa", {"@0x1": ["@0x1", "E47HYX2O"], "@0x4": "*0x1", "@0x5": "#0x4"}], "0x3c": ["@0xa", {"@0x1": ["@0x1", "KE36JYS7"], "@0x4": "*0x2", "@0x5": "#0x4"}]}, "assets": {"0x1": ["@0x4", {"@0x1": ["@0x1", "J7PIKN69"], "@0x2": "#0x37"}], "0x2": ["@0x4", {"@0x1": ["@0x1", "3G01JOA5"], "@0x2": "#0x37"}], "0x3": ["@0x4", {"@0x1": ["@0x1", "JSW5L3JH"], "@0x2": "#0x37"}], "0x4": ["@0x4", {"@0x1": ["@0x1", "59ONLYJX"], "@0x2": "#0x37"}], "0x5": ["@0x4", {"@0x1": ["@0x1", "50K97FJ6"], "@0x2": "#0x37"}], "0x6": ["@0x4", {"@0x1": ["@0x1", "AWZYDLB9"], "@0x2": "#0x37"}], "0x7": ["@0x4", {"@0x1": ["@0x1", "AO411BM0"], "@0x2": "#0x37"}], "0x8": ["@0x4", {"@0x1": ["@0x1", "O3ZYSC42"], "@0x2": "#0x37"}], "0x9": ["@0x4", {"@0x1": ["@0x1", "LPZZG8NE"], "@0x2": "#0x37"}], "0xa": ["@0x4", {"@0x1": ["@0x1", "426GBP10"], "@0x2": "#0x37"}]}}, "cache": {"names": {"0x1": "name", "0x2": "file", "0x3": "path", "0x4": "asset", "0x5": "transform", "0x6": "position", "0x7": "vec3", "0x8": "rotation", "0x9": "scale", "0xa": "object"}, "objects": {"0x2": ["@0x7", [0.0, 0.0, 0.0]], "0x3": ["@0x7", [1.0, 1.0, 1.0]], "0x4": ["@0x5", {"@0x6": "#0x2", "@0x8": "#0x2", "@0x9": "#0x3"}], "0x37": ["@0x3", "Assets/TestAsset.obj"]}}} \ No newline at end of file diff --git a/python/__pycache__/neutrino.cpython-37.pyc b/python/__pycache__/neutrino.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e9bd73390a04a97af59292c32a6bf784e6a575fe GIT binary patch literal 3520 zcmaJ@O>7&-6`sFcE>{#y%Zh$n!!?{BFca4;T%ajjIdzlND0*PgHmFiV0kh_;ELzl( znqAqnvAmSI^iUKqil9JMKsxr?Yi~W}*h5cq?a8;Cb?WzKmNXTo-NpRB`Fr1c-T~{p>vbLK8frpEy8bzPAa$&l zP%7Qf%P0fg)E7{Ox}`6otmzef31y^L^&2Sbn*W-$H(p|O*7>+6sKiIx){s6#%I_f4 zykxsV3)=Wt_F13l;8?gaJQgL_H68V5dHop2I93x;3M{_Vu_{Xr(zdX{?qHY{kFXxT zuYQakHA;%T=i=6P+tSeHHpqL)AhmIl=V{TUQJR&&Tx7R+sJ`0#PsD{>q3 zGo6kN#|mv}gI?0xOKtNY8F#%zcRzh*8`P$W)M_iM4$>mA!6TE5_Dq8|kNR1Wnk*Uo z4a>Om_iSgt@y0}z+>3?&5hrk3Fc+vsAiX3#pYdy!Jr8a@&WD-hPhZj{+uVkPL{_vzyW~*t8nCK2 zgi2~A9SxFRYSnO*W>&emN*^7J+JU)*1#D!}L?;i)0(yfq$-1O@8}0T7DIo{Mj|ytM z0>iA*yf{yuq<*h&qn#60Of+~TBN>V-yulS;5$0|5_UQEV(N*ZwPSJ0nLdx~3UWbw= zFnP@bMyh`g9^0q7Usj8HKjo6}UZILx-EpX{LsHvHGpEC6%K17p4iH5f8WTQ5wK<-0?3V58A6?-zX#kb08#zF!3v$V6sXBs5@%P3Hk; z0ZejV%ipn~4-kf;-2%eWBm6G)lB>4E1(@k9cBzUi4rj7@^Bu~Fczot~sgaM8r&$$+ zev2`0_hOaDu=mUOuLqQGNJC+E&IoiII=VA~f1?5g@+mLK*Z(#CCju@)!ijJ&{2efO zYnPB9@Bg8O%J;*G$`sfG9Fbqfd`WX4p&;>~2uk!!LHR{UA!3Tv2}(c!j@hr7KNU69 z;WOwD%aCU4@L2lsGT34naS~)p@+qrmmOaI?hk~6ZafmrZ5Aqi#v`+ z&3m}ueM7GxTL)KmT{K4oo~soheRz}=zJuuFjKA5AtSX+3QX3RUBSZwk%F4VjR_T7P zu**Gq1$0RSbY#_DlJ9veYd)&is-cB#;(p$(n9RnG#JV(Xw$_Z~&Vy_|z|IFq`Bh{T zb=Ht#p|}z)lnvPc&#j>jlu7oRQT{VV#xE*lJ;(p9LY5Og1-aDC*N|<3&t}LH_MJk_ zkqzKdGi2pSsFe;*1>sbJ2Z;+c-{+=TwSnO)jHvG}J8V`+Mdy&Zi=#ScG=zmS{C3R& zVBV*WdzAeInZ0n7orA%UK^xK&CeWM9d_>tCX!BEQ-bZHZe&Xvf)%*;@zemc657;+o zyCqholbXl+2!eBe`U(x$YW1k9YIs0B5))23>T^7A@vKGMy;*V)-CLl)tEH?W?~12A z=v|bcS(F_O2XlxzXb--yyUqUZE>70% za)Mo6xLs=FYh}3b4)7#QJJd>rHNV6=fV>w}t!rD}*Ooh;{T$JeI{Y)nJ(-315p|FQ z`pi)oVT({VuX~gTG`OZ?Mlxon=XT_uZ*gy!6-hr!O>SfIoUQ}WFFFU=JGmRNjXX8| zWKhX{&9Sav{Zpj;8Zstg-c(Hx=L%nuim&mja#mmAEon%)%|CAQ`|a4!4EL~hZ$9Vu yp3-mA0CBBzMR$5PbAh?tDI9%ATL(jZG)UhkHMvJ+B;#+zm!deLv>IKBHvS7u4b8m( literal 0 HcmV?d00001 diff --git a/python/neutrino/__pycache__/decode.cpython-37.pyc b/python/neutrino/__pycache__/decode.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..37aebe8137688bbceb7406e1eaf3596da44504fc GIT binary patch literal 709 zcmZ`%&2G~`5T4!j#y=uGKr2WO2!Vu@3URJbRaLa-TsRb2M$zJ3k+lAce;|?UUdmel zQhelHc!Irhf(PJ`6SHMh3YU?31gPN_GwClkakoGs$Rr8j#v|)>rOTgHw88X?+ zi`w2Y9QO<*-(}wt0(X4$KYVm?a|z2A+kTw8ejfE~wW)JWPc=t%y7;kGr>O4K4$j4! zXe(Bw(ELL#ve}sCW|lb)7&H$>I8)kA-(RV)EH>oXhCJ0g5wXJHY&_7`Rgor|%PP(a z&F7_x3vK5ri$th2k5VD=bC%DOa_su{Jef*S3g6ADT=me&#iywu@m+&@L3XWHntv2g zh2mL?)hhQ7sw5NPwUX1moj%uh(yHvJzC->1o8BBPUIpi=RKY}5B`T*uwkl_75+u7= zsu15_W-C3cl1_12gepajg?NF4H*c7&-6`sFcE>{#y%Zh$n!!_I>Fca4;T%ajjIdzlND0*PgHmDLq0kh_;ELzl( znqAqnvAmSI^iUKqil9JMKsxr?Yi~W}*h5cq?a8;Cb?WzKmNXTo-NpRB`Fr1c-<$WB zmt%(S@WornKQe|=MCBe*{xLGmG#{`BOs{FF)#v;H*XugeHPnQTbp3PoKNilGMWts#AYl;1(7 zdC7K#7PRrP?6W@8!Le{6CMPgPU;o6M{hXiYgse!@=~DO&Tp zBq1T8kb+HiBFHvQVHxXeA`4kcU7w0S-k7M8o6idMI4DJ_$X@;+Im;S_I&nRxg0pSd z+OOEJ*~cgWVWVR%;sj0^<^t6StCytiGk(po=fSPV`7pEm=}Wp~o7<28$%=MpmmC;g z16K8hP)W_Cqe0S3ts0Kf%qllm>7#>DJ2029fQ?L==;R?8LT`{JS(gB?(Qbc`5`X~y zsG!CxOw20Hi}U13>i7CK+BreSM1w~%lA*Z58(i@fVctS-k4{e?U4>5V6#XVDq+GA+ zbtriP%hx<$r22Q^7+b6)mysQ_1X)9P;=Xb(9k+$+vJ&R?^@G*O3ebNW;(3USiI!{$ z(?;zaI>lf)k?ham| zkI_`j%98K;x~Tf(6i%@#`p}M(QE1Cuf!o71bhyc!W@@NMn?M-jZj*L7u3sUw^UP&EEWP=XtY{^tl-!b#Aan0}hmcWENWzkmvt zptc4~5ZnV3{2@$GO@cDe%TTK`+9??+TBU#yexaMC`V0Fj0C1y#Xp0?wvF&9q%z>d* zTUdcWx`_J90x*|6Fy{MEgCVoD^}-}szB@DrHX04{e$fX3sV8ag2UUE5Ok{>dLIZ}_ zbRKsWz$Evz{B0ZhIAJL0Eg&pC!tYQoxoSIHfSJx>m#P5ca3-ra-=&O*$7hb08u=)B znpMH*6O4Jg7ppvmyh2pFw|EhBRA;$I_3N!4}JilOS7?U%{Us^{O2?-sGM)b-fJNaemsLxaaUPg&BBV z+;KE&-o*v)8+r`cI=Hgyf;s~6T&;-g!=tS59Yh~z{5$Q)s^ZxwwLx(-LPQ{}tjr5z zmG1WnyWFG4K$k>7M^^16`JTtJ=7W2!8d}&U?&sZ#$!zRMtV`2oYt2aRJjmvK?0kTf zUqwbyXALP9iYw7V*^mwJ+#2dYnPk5i`oV0zJLVhm_5MHb0~0ePp)oC%zt2&CfCXd!(HB zfPI6uTVho@sd=oAAUOA@uh4+4R*$Nxh6mImG2x`6KF2E;uUo|3ns}TViD-ko4xPt%H;1T$_TUS<+wA}D z;$+<}C)nkM+od+XR)!1j08hfSL#8 B(C+{M literal 0 HcmV?d00001 diff --git a/python/neutrino/decode.py b/python/neutrino/decode.py new file mode 100644 index 0000000..843832c --- /dev/null +++ b/python/neutrino/decode.py @@ -0,0 +1,30 @@ +import json + +def uncache_scene(in_data): + pure_data = { + "meta": in_data["meta"], + "graph": in_data["graph"] + } + raw_json = json.dumps(pure_data) + + # cache objects + raw_cache = json.dumps(in_data["cache"]) + for key, value in in_data["cache"]["objects"].items(): + pointer = "#" + key + raw_cache = raw_cache.replace(f'"{pointer}"', json.dumps(value)) + unpacked_object_cache = json.loads(raw_cache) + + # objects + for key, value in unpacked_object_cache.items(): + print(json.dumps(value)) + pointer = "#" + key + raw_json = raw_json.replace(f'"{pointer}"', json.dumps(value)) + + # names + for key, value in in_data["cache"]["names"].items(): + raw_json = raw_json.replace("@" + key, value) + + + out_data = json.loads(raw_json) + + return out_data \ No newline at end of file diff --git a/python/neutrino/encode.py b/python/neutrino/encode.py new file mode 100644 index 0000000..6758f21 --- /dev/null +++ b/python/neutrino/encode.py @@ -0,0 +1,189 @@ +import json + +# create a new scene graph +def new_scene(name, cache = True): + # create empty neutrino data + data = { + "meta": { + "name": ("name", name), + "scale": ("float", 1.0), + "asset_path": ("path", "./") + }, + "graph": { + "scene": {}, + "assets": {} + }, + "cache": { + "names": {}, + "objects": {} + }, + "internal": { + "cache": cache, + "max_object_key": {"index": 0}, + "max_name_key": {"index": 0} + } + } + + # return that empty data + return data + +# write the data to a JSON file +def save_scene(data, readable = False): + # cache the scene + if data["internal"]["cache"]: + cache_scene(data) + + # create working copy of the scene data + clean_data = data.copy() + + # get rid of internal data (not to be exported) + del clean_data["internal"] + + filename = data["meta"]["name"][1].replace(" ", "") + ".json" + with open(filename, "w") as outfile: + if readable: + json.dump(clean_data, outfile, indent = 4) + else: + json.dump(clean_data, outfile) + +# get a new indexed object key and track it +def new_key(index): + # get the indexed key + key = hex(index["index"] + 1) + + # index the max key + index["index"] += 1 + + return key + +# returns a cached name key from a string +def name_key(data, name): + if data["internal"]["cache"]: + name_pointer = "" + + # retrieve the proper key if it exists + for key, value in data["cache"]["names"].items(): + if value == name: + name_pointer = key + + # if the name pointer is still empty, make a new key and add it to the cache + if name_pointer == "": + name_pointer = new_key(data["internal"]["max_name_key"]) + data["cache"]["names"][name_pointer] = name + + return "@" + name_pointer + else: + return name + +# add an asset to the graph +def add_asset(data, name, path): + asset_data = { + name_key(data, "name"): (name_key(data, "name"), name), + name_key(data, "file"): (name_key(data, "path"), path) + } + + # add the asset to the graph + data["graph"]["assets"][new_key(data["internal"]["max_object_key"])] = (name_key(data, "asset"), asset_data) + +# add an object to the scene +def spawn_object(data, name, asset): + object_data = { + name_key(data, "name"): (name_key(data, "name"), name), + name_key(data, "asset"): "", + name_key(data, "transform"): (name_key(data, "transform"), { + name_key(data, "position"): (name_key(data, "vec3"), [0.0, 0.0, 0.0]), + name_key(data, "rotation"): (name_key(data, "vec3"), [0.0, 0.0, 0.0]), + name_key(data, "scale"): (name_key(data, "vec3"), [1.0, 1.0, 1.0]) + }) + } + + # get an asset key by the provided name + for key, value in data["graph"]["assets"].items(): + if value[1][name_key(data, "name")][1] == asset: + object_data[name_key(data, "asset")] = f"*{key}" + + # add the object to the scene + data["graph"]["scene"][new_key(data["internal"]["max_object_key"])] = (name_key(data, "object"), object_data) + +# recursively cache a single typeval tuple object +def cache_typeval(cache, typeval): + # ignore if not typeval + if type(typeval) == tuple: + for key, value in typeval[1].items(): + # refuse to cache pointers (that's just... that would just be a nightmare) + if type(value) == str: + is_pointer = ("*" in value) + else: + is_pointer = False + if not is_pointer: + # cache member objects if it's a dictionary object + if type(value[1]) == dict: + cache_typeval(cache, value) + + value_hash = hash(str(value)) + + # track in cache + if value_hash not in cache["objects"]: + cache_pointer = new_key(cache["key_index"]) + cache["objects"][value_hash] = {"key": cache_pointer, "value": value, "count": 1} + else: + cache_pointer = cache["objects"][value_hash]["key"] + cache["objects"][value_hash]["count"] += 1 + + # replace real value with hash + typeval[1][key] = "#" + cache_pointer + +# if there's only one instance of a certain value, convert it back to the original value and destroy the cached version +def uncache_typeval(cache, typeval): + for key, value in typeval[1].items(): + # refuse to cache pointers (that's just... that would just be a nightmare) + if type(value) == str: + is_pointer = ("*" in value) + else: + is_pointer = False + if not is_pointer: + # cache member objects if it's a dictionary object + if type(value[1]) == dict: + uncache_typeval(cache, value) + + value_hash = hash(str(value)) + + # check if it occurs only once + cache_key = value.replace("#", "") + if cache[cache_key]["count"] <= 1: + # replace the cache pointer in the scene data with its original value + typeval[1][key] = cache[cache_key]["value"] + + # delete this object from the cache + del cache[cache_key] + +# cache the scene +def cache_scene(data): + containers = [ + data["graph"]["scene"], + data["graph"]["assets"] + ] + + # build a cache of value hashes and pointers + hash_cache = {"key_index": {"index": 0}, "objects": {}} + for objects in containers: + for key, value in objects.items(): + cache_typeval(hash_cache, value) + + # create a cache hashed with pointer keys instead of value hashes + key_cache = {} + for key, value in hash_cache["objects"].items(): + key_cache[value["key"]] = {"value": value["value"], "count": value["count"]} + + # prune the cache to only redirect repeat values + for objects in containers: + for key, value in objects.items(): + uncache_typeval(key_cache, value) + + # create a serialized cache usable by neutrino + serial_cache = {} + for key, value in key_cache.items(): + serial_cache[key] = value["value"] + + # add that cache to the neutrino scene data + data["cache"]["objects"] = serial_cache \ No newline at end of file