Exemplo n.º 1
0
def stringToNodes(s,
                  hou_parent=None,
                  ne=None,
                  ignore_hdas_if_already_defined=None,
                  force_prefer_hdas=None,
                  override_network_position=None,
                  key=None):
    """
	TODO: here to be a docstring
	:param s:
	:param hou_parent:
	:param ne:
	:param ignore_hdas_if_already_defined:
	:param force_prefer_hdas:
	:override_network_position: hou.Vector2 - position in networkview pane
	:return:
	"""
    if ignore_hdas_if_already_defined is None:
        ignore_hdas_if_already_defined = True
        if opt is not None:
            ignore_hdas_if_already_defined = opt.getOption(
                'hpaste.ignore_hdas_if_already_defined',
                ignore_hdas_if_already_defined)

    if force_prefer_hdas is None:
        force_prefer_hdas = False
        if opt is not None:
            force_prefer_hdas = opt.getOption('hpaste.force_prefer_hdas',
                                              force_prefer_hdas)

    s = str(s)  # ununicode. there should not be any unicode in it anyways
    try:
        data = json.loads(bz2.decompress(base64.urlsafe_b64decode(s)))
    except Exception as e:
        raise RuntimeError(
            "input data is either corrupted or just not a nodecode: " +
            str(e.message))

    houver1 = hou.applicationVersion()

    paste_to_position = ne is not None or override_network_position is not None
    if hou_parent is None:
        if ne is None:
            nes = [
                x for x in hou.ui.paneTabs()
                if x.type() == hou.paneTabType.NetworkEditor
                and getChildContext(x.pwd(), houver1) == data['context']
            ]
            if len(nes) == 0:
                nes = [
                    x for x in hou.ui.paneTabs()
                    if x.type() == hou.paneTabType.NetworkEditor
                ]
                if len(nes) == 0:
                    raise RuntimeError(
                        "this snippet has '{0}' context. cannot find opened network editor with context '{0}' to paste in"
                        .format(data['context']))
            ne = nes[0]
        hou_parent = ne.pwd()

    # check version
    formatVersion = data['version']
    if formatVersion > current_format_version[0]:
        raise RuntimeError(
            "unsupported version of data format. Try updating hpaste to the latest version"
        )
    if data.get('version.minor', 0) > current_format_version[1]:
        print(
            'HPaste: Warning!! snippet has later format version than hpaste. Consider updating hpaste to the latest version'
        )
    if data.get('signed', False):
        print(
            'HPaste: Warning!! this snippet seem to be signed, but this version of HPaste has no idea how to check signatures! so signature check will be skipped!'
        )

    # check accepted algtypes
    supportedAlgs = set()
    if houver1[0] == 15:
        supportedAlgs.add(0)
        supportedAlgs.add(1)
        supportedAlgs.add(2)  # WITH BIG WARNING!!!
    if houver1[0] >= 16:
        supportedAlgs.add(0)
        supportedAlgs.add(1)
        supportedAlgs.add(2)
    algtype = data['algtype']
    if algtype not in supportedAlgs:
        raise RuntimeError(
            "algorithm type is not supported by this houdini version, :( ")

    # check hou version
    houver2 = data['houver']
    if not opt.getOption('hpaste.ignore_houversion_warning', False) and (
            houver1[0] != houver2[0] or houver1[1] != houver2[1]):
        print(
            "HPaste: WARNING!! nodes were copied from a different houdini version: "
            + str(houver2))

    # check context
    context = getChildContext(hou_parent, houver1)
    if context != data['context']:
        raise InvalidContextError(
            hou_parent, data['context']
        )  # RuntimeError("this snippet has '%s' context" % data['context'])

    # check sum
    code = data['code']
    if hashlib.sha1(code).hexdigest() != data['chsum']:
        raise RuntimeError("checksum failed!")

    if paste_to_position:
        if houver1[0] >= 16:
            olditems = hou_parent.allItems()
        else:
            olditems = hou_parent.children()

    deserialize = getDeserializer(enctype=data.get('encryptionType', None),
                                  key=key,
                                  **(data.get('encryptionData', None) or {}))

    # do the work
    for hdaitem in data.get('hdaList', []):  # added in version 2.1
        hdacode = deserialize(hdaitem['code'])
        ntype = hdaitem['type']
        ncategory = hdaitem['category']
        if ignore_hdas_if_already_defined:
            nodeType = hou.nodeType(hou.nodeTypeCategories()[ncategory], ntype)
            if nodeType is not None:
                # well, that's already a bad sign, means it is installed
                continue

        fd, temppath = tempfile.mkstemp()
        try:
            with open(temppath, 'wb') as f:
                f.write(hdacode)
            for hdadef in hou.hda.definitionsInFile(temppath):
                hdadef.copyToHDAFile('Embedded')
                # hdadef.save('Embedded')
        finally:
            os.close(fd)

        if force_prefer_hdas:
            embhdas = [
                x for x in hou.hda.definitionsInFile("Embedded")
                if (x.nodeType().name() == ntype
                    and x.nodeTypeCategory().name() == ncategory)
            ]
            if len(embhdas) == 1:
                embhdas[0].setIsPreferred(True)

    # now nodes themselves
    if formatVersion == 1:
        code = binascii.a2b_qp(code)
    elif formatVersion >= 2:
        code = deserialize(code)
    else:
        raise RuntimeError(
            "Very unexpected format version in a very unexpected place!")

    load_warnings = []
    if algtype == 0:
        # high security risk!!
        if hou.isUiAvailable():
            ok = hou.ui.displayMessage(
                "WARNING! The algorithm type used by the pasted snipped is legacy and present HIGH SECURITY RISK!\n be sure you TRUST THE SOURCE of the snippet!",
                ("CANCEL", "ok"),
                severity=hou.severityType.Warning,
                close_choice=0,
                title="SECURITY WARNING")
        else:
            ok = 0
            print(
                "for now u cannot paste SECURITY RISK snippets in non-interactive mode"
            )
        if ok != 1:
            return

        exec(code, {}, {'hou': hou, 'hou_parent': hou_parent})
    elif algtype == 1 or algtype == 2:
        # get temp file
        fd, temppath = tempfile.mkstemp()
        try:
            with open(temppath, "wb") as f:
                f.write(code)
            try:
                if algtype == 1:
                    hou_parent.loadChildrenFromFile(temppath)
                if algtype == 2:
                    try:
                        hou_parent.loadItemsFromFile(temppath)
                    except AttributeError:
                        print(
                            "WARNING!!! your hou version does not support algorithm used for copying, TRYING possibly partly backward-INCOMPATIBLE method!"
                        )
                        print("CHECK SCENE INTEGRITY")
                        hou_parent.loadChildrenFromFile(temppath)
            except hou.LoadWarning as e:
                msg = e.instanceMessage()
                print(msg)

                # truncate just for display with random number 253
                msgtrunc = False
                if len(msg) > 253:
                    msgtrunc = True
                    msg = msg[:253] + "..."
                load_warnings.append("There were warnings during load" + (
                    "(see console for full message)" if msgtrunc else "") +
                                     "\n" + msg)
        finally:
            os.close(fd)
    else:
        raise RuntimeError(
            "algorithm type is not supported. Try updating hpaste to the latest version"
        )

    if paste_to_position:
        # now collect pasted nodes
        if houver1[0] >= 16:
            newitems = [x for x in hou_parent.allItems() if x not in olditems]
        else:
            newitems = [x for x in hou_parent.children() if x not in olditems]

        if len(newitems) == 0:
            return
        # calc center
        cpos = hou.Vector2()
        bbmin = hou.Vector2()
        bbmax = hou.Vector2()
        cnt = 0
        for item in newitems:
            cnt += 1
            pos = item.position()
            cpos += pos
            for i in [0, 1]:
                if pos[i] > bbmax[i] or cnt == 1:
                    bbmax[i] = pos[i]
                if pos[i] < bbmin[i] or cnt == 1:
                    bbmin[i] = pos[i]

        cpos = cpos / cnt
        cpos[1] = bbmax[1]
        if override_network_position is None:
            offset = ne.cursorPosition() - cpos
        else:
            offset = override_network_position - cpos
        for item in newitems:
            if houver1[0] >= 16 and item.parentNetworkBox() in newitems:
                continue
            item.move(offset)

    if len(load_warnings) > 0:
        raise RuntimeWarning('snippet loaded with following warnings:\n' +
                             '\n'.join(load_warnings))
Exemplo n.º 2
0
def stringToNodes(s, hou_parent=None, ne=None):
    paste_to_cursor = ne is not None
    if (hou_parent is None):
        if (ne is None):
            ne = hou.ui.paneTabOfType(hou.paneTabType.NetworkEditor)
            if (ne is None):
                raise RuntimeError("cannot find opened network editor")
        hou_parent = ne.pwd()

    s = str(s)  # ununicode. there should not be any unicode in it anyways
    try:
        data = json.loads(bz2.decompress(base64.urlsafe_b64decode(s)))
    except Exception as e:
        raise RuntimeError(
            "input data is either corrupted or just not a nodecode: " +
            str(e.message))

    # check version
    formatVersion = data['version']
    if (formatVersion > 2):
        raise RuntimeError("unsupported version of data format")

    # check accepted algtypes
    houver1 = hou.applicationVersion()
    supportedAlgs = set()
    if (houver1[0] == 15):
        supportedAlgs.add(0)
        supportedAlgs.add(1)
        supportedAlgs.add(2)  #WITH BIG WARNING!!!
    if (houver1[0] >= 16):
        supportedAlgs.add(0)
        supportedAlgs.add(1)
        supportedAlgs.add(2)
    algtype = data['algtype']
    if (algtype not in supportedAlgs):
        raise RuntimeError(
            "algorithm type is not supported by this houdini version, :( ")

    # check hou version
    houver2 = data['houver']
    if (houver1[0] != houver2[0] or houver1[1] != houver2[1]):
        print(
            "HPaste: WARNING!! nodes were copied from a different houdini version: "
            + str(houver2))

    # check context
    context = getChildContext(hou_parent, houver1)
    if (context != data['context']):
        raise RuntimeError("this snippet has '%s' context" % data['context'])

    # check sum
    code = data['code']
    if (hashlib.sha1(code).hexdigest() != data['chsum']):
        raise RuntimeError("checksum failed!")

    if (paste_to_cursor):
        if (houver1[0] == 16):
            olditems = hou_parent.allItems()
        else:
            olditems = hou_parent.children()

    # do the work
    if (formatVersion == 1):
        code = binascii.a2b_qp(code)
    elif (formatVersion >= 2):
        code = base64.b64decode(code)
    else:
        raise RuntimeError(
            "Very unexpected format version in a very inexpected place!")

    if (algtype == 0):
        # high security risk!!
        if (hou.isUiAvailable()):
            ok = hou.ui.displayMessage(
                "WARNING! The algorithm type used by the pasted snipped is legacy and present HIGH SECURITY RISK!\n be sure you TRUST THE SOURCE of the snippet!",
                ("CANCEL", "ok"),
                severity=hou.severityType.Warning,
                close_choice=0,
                title="SECURITY WARNING")
        else:
            ok = 0
            print(
                "for now u cannot paste SECURITY RISK snippets in non-interactive mode"
            )
        if (ok != 1): return

        exec(code, {}, {'hou': hou, 'hou_parent': hou_parent})
    elif (algtype == 1 or algtype == 2):
        # get temp file
        fd, temppath = tempfile.mkstemp()
        try:
            with open(temppath, "wb") as f:
                f.write(code)
            try:
                if (algtype == 1):
                    hou_parent.loadChildrenFromFile(temppath)
                if (algtype == 2):
                    try:
                        hou_parent.loadItemsFromFile(temppath)
                    except AttributeError:
                        print(
                            "WARNING!!! your hou version does not support algorithm used for copying, TRYING possibly partly backward-INCOMPATIBLE method!"
                        )
                        print("CHECK SCENE INTEGRITY")
                        hou_parent.loadChildrenFromFile(temppath)
            except hou.LoadWarning as e:
                msg = e.instanceMessage()
                print(msg)

                # truncate just for display with random number 253
                msgtrunc = False
                if (len(msg) > 253):
                    msgtrunc = True
                    msg = msg[:253] + "..."
                raise RuntimeWarning("There were warnings during load" + (
                    "(see console for full message)" if msgtrunc else "") +
                                     "\n" + msg)
        finally:
            os.close(fd)
    else:
        raise RuntimeError("algorithm type is not supported")

    if (paste_to_cursor):
        #now collect pasted nodes
        if (houver1[0] >= 16):
            newitems = [x for x in hou_parent.allItems() if x not in olditems]
        else:
            newitems = [x for x in hou_parent.children() if x not in olditems]

        if (len(newitems) == 0): return
        #calc center
        cpos = hou.Vector2()
        bbmin = hou.Vector2()
        bbmax = hou.Vector2()
        cnt = 0
        for item in newitems:
            cnt += 1
            pos = item.position()
            cpos += pos
            for i in [0, 1]:
                if (pos[i] > bbmax[i]): bbmax[i] = pos[i]
                if (pos[i] < bbmin[i]): bbmin[i] = pos[i]

        cpos = cpos / cnt
        cpos[1] = bbmax[1]
        offset = ne.cursorPosition() - cpos
        for item in newitems:
            if (houver1[0] >= 16 and item.parentNetworkBox() in newitems):
                continue
            item.move(offset)