def getValueAsString(self, i:int = 0)->str:
        value = self.getValue(i)

        if value == None:
            return ''

        # convert floats to strings
        if isinstance(value, float):
            value = floatToStr(value)
        # convert ints to strings
        elif isinstance(value, int):
            value = str(value)
        # convert lists to strings
        elif isinstance(value, list) or isinstance(value, tuple) and len(value) > 0:
            _value = []
            for i in range(0, len(value)):
                # convert floats to strings
                if isinstance(value[i], float):
                    _value.append(floatToStr(value[i]))
                else:
                    _value.append(str(value[i]))

            value = '\t'.join(_value)
        elif not isinstance(value, str):
            value = ''

        return value
Exemple #2
0
    def getValueAsString(self, i: int = 0) -> str:
        value = self.getValue(i)

        if value == None:
            return ''

        # convert floats to strings
        if isinstance(value, float):
            value = floatToStr(value)
        # convert ints to strings
        elif isinstance(value, int):
            value = str(value)
        # convert lists to strings
        elif isinstance(value,
                        list) or isinstance(value, tuple) and len(value) > 0:
            _value = []
            for i in range(0, len(value)):
                # convert floats to strings
                if isinstance(value[i], float):
                    _value.append(floatToStr(value[i]))
                else:
                    _value.append(str(value[i]))

            value = '\t'.join(_value)
        elif not isinstance(value, str):
            value = ''

        return value
Exemple #3
0
    def getValueAsString(self, i: int = 0) -> str:
        '''
        Gets the value of value[i] as a formatted string.
        If self.value[i] is a list, the list's string representation
        will be seperated with '\t's instead of ','s
        '''
        value = self.getValue(i)

        if value is None:
            return ''

        # convert floats to strings
        if isinstance(value, float):
            value = floatToStr(value)
        # convert ints to strings
        elif isinstance(value, int):
            value = str(value)
        # convert lists to strings
        elif isinstance(value,
                        list) or isinstance(value, tuple) and len(value) > 0:
            value = tuple(value)  # satisfies pylint "value is unsubscriptable"
            _value = []
            for i in range(0, len(value)):
                # convert floats to strings
                if isinstance(value[i], float):
                    _value.append(floatToStr(value[i]))
                else:
                    _value.append(str(value[i]))

            value = '\t'.join(_value)
        elif not isinstance(value, str):
            value = ''

        return value
    def parseAttributeValue(self, value, blenderObject):
        if str(value).find('{{xyz}}') != -1:
            return str(value).replace('{{xyz}}', '%6.8f\t%6.8f\t%6.8f' % (
                xplane_helpers.floatToStr(blenderObject.location[0]),
                xplane_helpers.floatToStr(blenderObject.location[2]),
                xplane_helpers.floatToStr(-blenderObject.location[1])
            ))

        return value
Exemple #5
0
    def parseAttributeValue(self, value, blenderObject):
        if str(value).find('{{xyz}}') != -1:
            return str(value).replace(
                '{{xyz}}', '%6.8f\t%6.8f\t%6.8f' %
                (xplane_helpers.floatToStr(blenderObject.location[0]),
                 xplane_helpers.floatToStr(blenderObject.location[2]),
                 xplane_helpers.floatToStr(-blenderObject.location[1])))

        return value
    def _writeStaticRotation(self, bakeMatrix):
        debug = getDebug()
        indent = self.getIndent()
        o = ''
        bakeMatrix = bakeMatrix
        rotation = bakeMatrix.to_euler('XYZ')
        rotation[0] = round(rotation[0],5)
        rotation[1] = round(rotation[1],5)
        rotation[2] = round(rotation[2],5)
        
        # ignore noop rotations
        if rotation[0] == 0 and rotation[1] == 0 and rotation[2] == 0:
            return o

        if debug:
            o += indent + '# static rotation\n'

		# Ben says: this is SLIGHTLY counter-intuitive...Blender axes are
		# globally applied in a Euler, so in our XYZ, X is affected -by- Y
		# and both are affected by Z.
		#
		# Since X-Plane works opposite this, we are going to apply the
		# animations exactly BACKWARD! ZYX.  The order here must
		# be opposite the decomposition order above.
		#
		# Note that since our axis naming is ALSO different this will
		# appear in the OBJ file as Y -Z X.
		#
		# see also: http://hacksoflife.blogspot.com/2015/11/blender-notepad-eulers.html

        axes = (2, 1, 0)
        eulerAxes = [(0.0,0.0,1.0),(0.0,1.0,0.0),(1.0,0.0,0.0)]
        i = 0

        for axis in eulerAxes:
            deg = math.degrees(rotation[axes[i]])

            # ignore zero rotation
            if not deg == 0:
                o += indent + 'ANIM_rotate\t%s\t%s\t%s\t%s\t%s\n' % (
                    floatToStr(axis[0]),
                    floatToStr(axis[2]),
                    floatToStr(-axis[1]),
                    floatToStr(deg), floatToStr(deg)
                )

            i += 1

        return o
    def _writeEulerRotationKeyframes(self, dataref, keyframes):
        debug = getDebug()
        o = ''
        indent = self.getIndent()
        axes, final_rotation_mode = keyframes.getReferenceAxes()
        totalRot = 0

        for axis,order in zip(axes,XPlaneKeyframeCollection.EULER_AXIS_ORDERING[final_rotation_mode]):
            ao = ''
            totalAxisRot = 0

            ao += "%sANIM_rotate_begin\t%s\t%s\t%s\t%s\n" % (
                indent,
                floatToStr(axis[0]),
                floatToStr(axis[2]),
                floatToStr(-axis[1]),
                dataref
            )


            for keyframe in keyframes:
                deg = math.degrees(keyframe.rotation[order])
                totalRot += abs(deg)
                totalAxisRot += abs(deg)

                ao += "%sANIM_rotate_key\t%s\t%s\n" % (
                    indent,
                    floatToStr(keyframe.value),
                    floatToStr(deg)
                )

            ao += self._writeKeyframesLoop(dataref)
            ao += "%sANIM_rotate_end\n" % indent

            # do not write non-animated axis
            if round(totalAxisRot, FLOAT_PRECISION) > 0:
                o += ao

        # do not write zero rotations
        if round(totalRot, FLOAT_PRECISION) == 0:
            return ''

        return o
    def _writeAxisAngleRotationKeyframes(self, dataref, keyframes):
        o = ''
        indent = self.getIndent()
        totalRot = 0

        # our reference axis (or axes)
        axes, final_rotation_mode = keyframes.getReferenceAxes()

        if len(axes) == 3:
            # decompose to eulers and return euler rotation instead
            o = self._writeEulerRotationKeyframes(dataref,keyframes.asEuler())
            return o
        elif len(axes) == 1:
            refAxis = axes[0]

        o += "%sANIM_rotate_begin\t%s\t%s\t%s\t%s\n" % (
            indent,
            floatToStr(refAxis[0]),
            floatToStr(refAxis[2]),
            floatToStr(-refAxis[1]),
            dataref
        )

        for keyframe in keyframes:
            deg = math.degrees(keyframe.rotation[0])
            totalRot += abs(deg)

            o += "%sANIM_rotate_key\t%s\t%s\n" % (
                indent,
                floatToStr(keyframe.value),
                floatToStr(deg)
            )

        o += self._writeKeyframesLoop(dataref)
        o += "%sANIM_rotate_end\n" % indent

        # do not write zero rotations
        if round(totalRot, FLOAT_PRECISION) == 0:
            return ''

        return o
    def _writeStaticTranslation(self, bakeMatrix):
        debug = getDebug()
        indent = self.getIndent()
        o = ''

        bakeMatrix = bakeMatrix

        translation = bakeMatrix.to_translation()
        translation[0] = round(translation[0],5)
        translation[1] = round(translation[1],5)
        translation[2] = round(translation[2],5)

        # ignore noop translations
        if translation[0] == 0 and translation[1] == 0 and translation[2] == 0:
            return o

        if debug:
            o += indent + '# static translation\n'

        o += indent + 'ANIM_trans\t%s\t%s\t%s\t%s\t%s\t%s\n' % (
            floatToStr(translation[0]),
            floatToStr(translation[2]),
            floatToStr(-translation[1]),
            floatToStr(translation[0]),
            floatToStr(translation[2]),
            floatToStr(-translation[1])
        )

        return o
Exemple #10
0
    def _writeTranslationKeyframes(self, dataref):
        debug = getDebug()
        keyframes = self.animations[dataref]
        
        o = ''
        
        if not self.isDataRefAnimatedForTranslation():
            return o
        
        # Apply scaling to translations
        pre_loc, pre_rot, pre_scale = self.getPreAnimationMatrix().decompose()
        
        totalTrans = 0
        indent = self.getIndent()

        if debug:
            o += indent + '# translation keyframes\n'

        o += "%sANIM_trans_begin\t%s\n" % (indent, dataref)

        for keyframe in keyframes:
            totalTrans += abs(keyframe.location[0]) + abs(keyframe.location[1]) + abs(keyframe.location[2])

            o += "%sANIM_trans_key\t%s\t%s\t%s\t%s\n" % (
                indent, floatToStr(keyframe.value),
                floatToStr(keyframe.location[0] * pre_scale[0]),
                floatToStr(keyframe.location[2] * pre_scale[2]),
                floatToStr(-keyframe.location[1] * pre_scale[1])
            )

        o += self._writeKeyframesLoop(dataref)
        o += "%sANIM_trans_end\n" % indent

        # do not write zero translations
        if totalTrans == 0:
            return ''

        return o
    def write(self) -> str:
        """
        Writes the combined Blender and XPlane2Blender data,
        raises UnwritableXPlaneType if logger errors found
        """
        debug = xplane_config.getDebug()
        indent = self.xplaneBone.getIndent()
        o = super().write()

        special_empty_props = self.blenderObject.xplane.special_empty_props

        if (int(bpy.context.scene.xplane.version) >= 1130 and
            (special_empty_props.special_type == EMPTY_USAGE_EMITTER_PARTICLE
             or special_empty_props.special_type
             == EMPTY_USAGE_EMITTER_SOUND)):
            if not self.xplaneBone.xplaneFile.options.particle_system_file.endswith(
                    ".pss"):
                logger.error(
                    "Particle emitter {} is used, despite no .pss file being set"
                    .format(self.blenderObject.name))
                return ""
            elif special_empty_props.emitter_props.name.strip() == "":
                logger.error(
                    "Particle name for emitter {} can't be blank".format(
                        self.blenderObject.name))
                return ""

            bake_matrix = self.xplaneBone.getBakeMatrixForAttached()
            em_location = xplane_helpers.vec_b_to_x(
                bake_matrix.to_translation())
            #yaw,pitch,roll
            theta, psi, phi = tuple(
                map(math.degrees,
                    bake_matrix.to_euler()[:]))

            o += "{indent}EMITTER {name} {x} {y} {z} {phi} {theta} {psi}".format(
                indent=indent,
                name=special_empty_props.emitter_props.name,
                x=floatToStr(em_location.x),
                y=floatToStr(em_location.y),
                z=floatToStr(em_location.z),
                phi=floatToStr(-phi),  #yaw right
                theta=floatToStr(theta),  #pitch up
                psi=floatToStr(psi))  #roll right

            if (special_empty_props.emitter_props.index_enabled
                    and special_empty_props.emitter_props.index >= 0):
                o += ' {}'.format(special_empty_props.emitter_props.index)

            o += '\n'
        elif (int(bpy.context.scene.xplane.version) >= 1130
              and special_empty_props.special_type == EMPTY_USAGE_MAGNET):
            bake_matrix = self.xplaneBone.getBakeMatrixForAttached()
            em_location = xplane_helpers.vec_b_to_x(
                bake_matrix.to_translation())
            #yaw,pitch,roll
            theta, psi, phi = tuple(
                map(math.degrees,
                    bake_matrix.to_euler()[:]))

            o += "{indent}MAGNET {debug_name} {magnet_type} {x} {y} {z} {phi} {theta} {psi}\n".format(
                indent=indent,
                debug_name=special_empty_props.magnet_props.debug_name,
                magnet_type=self.magnet_type,
                x=floatToStr(em_location.x),
                y=floatToStr(em_location.y),
                z=floatToStr(em_location.z),
                phi=floatToStr(-phi),  #yaw right
                theta=floatToStr(theta),  #pitch up
                psi=floatToStr(psi))  #roll right

        return o