Worker: check BLENDER_CMD environment variable (for multi-GPU Eevee rendering) #104193

Open
MKRelax wants to merge 9 commits from MKRelax/flamenco:worker-use-blender-from-env into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
11 changed files with 394 additions and 208 deletions

View File

@ -4,7 +4,7 @@
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**value** | **str** | | must be one of ["file_association", "path_envvar", "input_path", ]
**value** | **str** | | must be one of ["file_association", "path_envvar", "input_path", "env_variable", ]
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@ -55,6 +55,7 @@ class BlenderPathSource(ModelSimple):
'FILE_ASSOCIATION': "file_association",
'PATH_ENVVAR': "path_envvar",
'INPUT_PATH': "input_path",
'ENV_VARIABLE': "env_variable",
},
}
@ -106,10 +107,10 @@ class BlenderPathSource(ModelSimple):
Note that value can be passed either in args or in kwargs, but not in both.
Args:
args[0] (str):, must be one of ["file_association", "path_envvar", "input_path", ] # noqa: E501
args[0] (str):, must be one of ["file_association", "path_envvar", "input_path", "env_variable", ] # noqa: E501
Keyword Args:
value (str):, must be one of ["file_association", "path_envvar", "input_path", ] # noqa: E501
value (str):, must be one of ["file_association", "path_envvar", "input_path", "env_variable", ] # noqa: E501
_check_type (bool): if True, values for parameters in openapi_types
will be type checked and a TypeError will be
raised if the wrong type is input.
@ -196,10 +197,10 @@ class BlenderPathSource(ModelSimple):
Note that value can be passed either in args or in kwargs, but not in both.
Args:
args[0] (str):, must be one of ["file_association", "path_envvar", "input_path", ] # noqa: E501
args[0] (str):, must be one of ["file_association", "path_envvar", "input_path", "env_variable", ] # noqa: E501
Keyword Args:
value (str):, must be one of ["file_association", "path_envvar", "input_path", ] # noqa: E501
value (str):, must be one of ["file_association", "path_envvar", "input_path", "env_variable", ] # noqa: E501
_check_type (bool): if True, values for parameters in openapi_types
will be type checked and a TypeError will be
raised if the wrong type is input.

View File

@ -24,6 +24,8 @@ var (
ErrTimedOut = errors.New("version check took too long")
)
const BlenderPathEnvVariable = "FLAMENCO_BLENDER_PATH"
// blenderVersionTimeout is how long `blender --version` is allowed to take,
// before timing out. This can be much slower than expected, when loading
// Blender from shared storage on a not-so-fast NAS.
@ -50,7 +52,44 @@ func FileAssociation() (string, error) {
return fileAssociation()
}
// EnvironmentVariable returns the full path of a Blender executable, by checking the environment.
MKRelax marked this conversation as resolved Outdated

I think the name of this variable should be in a constant. Can be in the same file. That way the string literal doesn't get repeated everywhere.

I think the name of this variable should be in a constant. Can be in the same file. That way the string literal doesn't get repeated everywhere.
func EnvironmentVariable() (string, string, error) {
// Check the environment for a full path
fullPath := os.Getenv(BlenderPathEnvVariable)
if fullPath == "" {
return BlenderPathEnvVariable, "", nil
}
// Make sure the path exists and is not a directory
stat, err := os.Stat(fullPath)
if err != nil {
return BlenderPathEnvVariable, fullPath, err
}
if stat.IsDir() {
return BlenderPathEnvVariable, fullPath, fmt.Errorf("Path from environment is a directory: %s", fullPath)
}
return BlenderPathEnvVariable, fullPath, nil
}
func CheckBlender(ctx context.Context, exename string) (CheckBlenderResult, error) {
// First check the exename, if given some form of path
if crosspath.Dir(exename) != "." {
// exename is some form of path, see if it works for us.
return checkBlenderAtPath(ctx, exename)
}
// Check the environment for a full path
_, envFullPath, err := EnvironmentVariable()
if err != nil {
return CheckBlenderResult{}, err
}
if envFullPath != "" {
return getResultWithVersion(ctx, exename, envFullPath, api.BlenderPathSourceEnvVariable)
}
if exename == "" {
// exename is not given, see if we can use .blend file association.
fullPath, err := fileAssociation()
@ -67,11 +106,6 @@ func CheckBlender(ctx context.Context, exename string) (CheckBlenderResult, erro
}
}
if crosspath.Dir(exename) != "." {
// exename is some form of path, see if it works for us.
return checkBlenderAtPath(ctx, exename)
}
// Try to find exename on $PATH
fullPath, err := exec.LookPath(exename)
if err != nil {

View File

@ -5,7 +5,9 @@ package find_blender
import (
"context"
"flag"
"os"
"os/exec"
"runtime"
"testing"
"github.com/stretchr/testify/assert"
@ -41,3 +43,62 @@ func TestGetBlenderVersion(t *testing.T) {
assert.ErrorIs(t, err, exec.ErrNotFound)
assert.Empty(t, version)
}
func TestGetBlenderCommandFromEnvironment(t *testing.T) {
// If the environment variable is unset, we expect an empty string
MKRelax marked this conversation as resolved Outdated

This should check that the environment variable isn't already set while running the test ;-)

This should check that the environment variable isn't already set while running the test ;-)
err := os.Unsetenv(BlenderPathEnvVariable)
assert.NoError(t, err, "Could not clear blender executable from environment")
envVar, path, err := EnvironmentVariable()
assert.NoError(t, err)
assert.Equal(t, BlenderPathEnvVariable, envVar)
assert.Equal(t, "", path)
MKRelax marked this conversation as resolved Outdated

The if and t.Fatal() can be replaced with require.NoError(t, err, "Could not set BLENDER_CMD environment variable").

The `if` and `t.Fatal()` can be replaced with `require.NoError(t, err, "Could not set BLENDER_CMD environment variable")`.
// If the environment variable is empty, we expect an empty string
err = os.Setenv(BlenderPathEnvVariable, "")
assert.NoError(t, err, "Could not set blender executable in environment")
envVar, path, err = EnvironmentVariable()
assert.NoError(t, err)
assert.Equal(t, BlenderPathEnvVariable, envVar)
assert.Equal(t, "", path)
// Try finding a non-existing executable in the environment variable
envExe := `D:\Blender_3.2_stable\blender.exe`
err = os.Setenv(BlenderPathEnvVariable, envExe)
assert.NoError(t, err, "Could not set blender executable in environment")
envVar, path, err = EnvironmentVariable()
assert.Error(t, err)
assert.Equal(t, path, envExe)
assert.Equal(t, BlenderPathEnvVariable, envVar)
// Try finding a existing file in the environment variable
// We use this filename instead of a real blender executable
_, myFilename, _, _ := runtime.Caller(0)
err = os.Setenv(BlenderPathEnvVariable, myFilename)
assert.NoError(t, err, "Could not set blender executable in environment")
envVar, path, err = EnvironmentVariable()
assert.NoError(t, err)
assert.Equal(t, path, myFilename)
assert.Equal(t, BlenderPathEnvVariable, envVar)
if !*withBlender {
t.Skip("skipping test, -withBlender arg not passed")
}
existingPath, err := exec.LookPath("blender")
if err != nil {
existingPath, err = fileAssociation()
if !assert.NoError(t, err) {
t.Fatal("running with -withBlender requires having a `blender` command on $PATH or a file association to .blend files")
}
}
// Try finding an existing executable in the environment variable
err = os.Setenv(BlenderPathEnvVariable, existingPath)
assert.NoError(t, err, "Could not set blender executable in environment")
envVar, path, err = EnvironmentVariable()
assert.NoError(t, err)
assert.Equal(t, path, existingPath)
assert.Equal(t, BlenderPathEnvVariable, envVar)
}

View File

@ -6,6 +6,7 @@ package worker
import (
"context"
"fmt"
"os/exec"
"regexp"
"sync"
@ -85,9 +86,17 @@ func (ce *CommandExecutor) cmdBlenderRenderCommand(
}
if crosspath.Dir(parameters.exe) == "." {
// No directory path given. Check that the executable can be found on the
// path.
if _, err := exec.LookPath(parameters.exe); err != nil {
// No directory path given. Check that the executable is set in an
// environment variable or can be found on the path.
envVar, envPath, err := find_blender.EnvironmentVariable()
if err != nil {
return nil, err

I wouldn't say "found Blender" here, because the path wasn't checked. Blender may not even exist there.

Maybe find_blender.EnvironmentVariable() can return two strings, (name, path) where name is the name of the environment variable, and path is the actual value. That way you can log here "using Blender from {environment variable name}".

I wouldn't say "found Blender" here, because the path wasn't checked. Blender may not even exist there. Maybe `find_blender.EnvironmentVariable()` can return two strings, `(name, path)` where `name` is the name of the environment variable, and `path` is the actual value. That way you can log here "using Blender from {environment variable name}".

I did change the log message to "using Blender from FLAMENCO_BLENDER_PATH".

However, since the name of the variable is (now) a constant I think there is no need to return it from find_blender.EnvironmentVariable(). Most code would not be interested in it anyway and probably ignore it using a _ variable. So the log message simply uses the constant.

I did change the log message to "using Blender from FLAMENCO_BLENDER_PATH". However, since the name of the variable is (now) a constant I think there is no need to return it from `find_blender.EnvironmentVariable()`. Most code would not be interested in it anyway and probably ignore it using a `_` variable. So the log message simply uses the constant.

I think it's still good to return the variable name. That way you get less coupling between the different parts of the code, making things more maintainable.

I think it's still good to return the variable name. That way you get less coupling between the different parts of the code, making things more maintainable.
}
if envPath != "" {
msg := fmt.Sprintf("using blender from %s", envVar)
logger.Info().Str("path", envPath).Msg(msg)
parameters.exe = envPath
} else if _, err := exec.LookPath(parameters.exe); err != nil {
// Attempt a platform-specific way to find which Blender executable to
// use. If Blender cannot not be found, just use the configured command
// and let the OS produce the errors.

View File

@ -2,6 +2,8 @@ package worker
import (
"context"
"os"
"runtime"
"testing"
"github.com/golang/mock/gomock"
@ -9,6 +11,7 @@ import (
"github.com/rs/zerolog/log"
"github.com/stretchr/testify/assert"
"projects.blender.org/studio/flamenco/internal/find_blender"
"projects.blender.org/studio/flamenco/pkg/api"
)
@ -79,6 +82,41 @@ func TestCmdBlenderCliArgsInExeParameter(t *testing.T) {
assert.Equal(t, ErrNoExecCmd, err, "nil *exec.Cmd should result in ErrNoExecCmd")
}
func TestCmdBlenderFromEnvironment(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
ce, mocks := testCommandExecutor(t, mockCtrl)
// We pass this file as blender executable because it must exist
// envExe := `D:\Blender_3.2_stable\blender.exe`
_, myFilename, _, _ := runtime.Caller(0)
envExe := myFilename
err := os.Setenv(find_blender.BlenderPathEnvVariable, envExe)
assert.NoError(t, err, "Could not set blender executable in environment")
taskID := "c5dfdfab-4492-4ab1-9b38-8ca4cbd84a17"
cmd := api.Command{
Name: "blender",
Parameters: map[string]interface{}{
// Passing "blender", the environment path should override this
"exe": "blender",
"argsBefore": []string{},
"blendfile": "file.blend",
"args": []string{},
},
}
mocks.cli.EXPECT().CommandContext(gomock.Any(),
envExe, // from environment variable
"file.blend", // from 'blendfile'
).Return(nil)
err = ce.cmdBlenderRender(context.Background(), zerolog.Nop(), taskID, cmd)
assert.Equal(t, ErrNoExecCmd, err, "nil *exec.Cmd should result in ErrNoExecCmd")
}
func TestProcessLineBlender(t *testing.T) {
ctx := context.Background()
mockCtrl := gomock.NewController(t)

View File

@ -1505,6 +1505,8 @@ components:
- path_envvar
# The input path was used as-is, as it points to an existing binary.
- input_path
# The input path was found in the $FLAMENCO_BLENDER_PATH environment variable.
- env_variable
WorkerRegistration:
type: object

View File

@ -49,201 +49,201 @@ var swaggerSpec = []string{
"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",
"/xMAAP//yoC45FYOAQA=",
"giolE041kmSzmwsmrq5oObCI4eQLJq4urmjJYW8xsu2shJ3jsQ9IyYxKBhI3JQpNUta2BeTvA0sqzTZZ",
"L/tNg57QB48dyONkKPgkdkovylKW3f38yAQreUKYeUxKpgopFIvZWdMI5v90dnZC0BhIzBtemvcDkWPD",
"WZOsStFqgndklUmaEiURyT0AcbUN2GaZXRoXaLbk0qiZz8xkD/cPPRPypoaUajqlqHpOK7UyzIoRWKhb",
"lOVlUmjKBaHk3lumy9Xo6Uyz8h6+umAUrBlmeVykPKGaKWuvQoVV8xzVb3MUTHldtGS65Cwdk5eguDop",
"xQ7IFcgxBk2okZUda7+nLBs07yYZZwKsKKkkSubM6IlzUjKqJBgrCEhX7APeJU4zMqXJpZzNkIF6+66T",
"LLvG5ZwpRecx3GshF5x7/X4Us66Y0D/L6bvC8PCo4qGY9obaITFHCzo7OZXJJdPHb/Ze/9vZGZ4hSpIo",
"aCgDxZIItjQ/qiGZFCW74rJSF4h0E29nYR8QxxACbYNYxjS7sAfF0gsa4RDHM6uaZgy4j6G8/gsrCDlr",
"Bs+Z0jQviKHQiA0GURwmmE+VliXKRi8zmjORSM+0m2dkYDYyI0aZToQCvXt3/NxJdD+DUX6DPb8Wk5oD",
"/ULzUBmMmx4a4N5Ey43s5H0RoXfDKyYP92PYWLJZydTiAmy5kaPxF9CLk/aKqAXYh+33QC3sbu4ptAzX",
"sipgHSoWytw2A3g1NEgHMmhKQaNgNFnAjb/iaUUz9EotYZa5IZVgLpHS3OCVG8Rah4uSJmC16rVS7A7E",
"fl8OTB1BjzOPnHJGMqq0XeXWOLek6gJvTNrjNMErarD8vVGc7cv1HTG3XUsy0WXFJlbZsE8KlvAZNy+D",
"bgYWRZ7eq23CiumhJavmJrnbnRd6tZUVDy6AA07gqLLup8BB1US6XsL2iir91hou+yicRVBZ1ghqIF8b",
"PHlO5zVzdNCzy4xL8Vu56oYDvajyqaA82wKtwq0cmxWB0yEm3+NcVF3af/lJ+sHEZ+zZKomJx54AZnzG",
"Rol5ibAr0OutHd1ogsDS1KJCxT6VSzE0kkUJf1bFkDCdxIj7NlY7vzhYKmo5rV33mtjwE6ouX8l53/mD",
"EzuTc5IsKnFpGZyWhBLga1oWPNlzvI6UUuYkZUjTUnzPCkAG5EP45Ury1IyTggDRIjgxOGQyov0/M+tx",
"NF7bVY7Ja7ry4k9eZZoXIFMIpuBd9kFH1Q2HEGtZErj7hzv6mGtUM9tYewzbSBlnAMYNYgaAoyNnADW4",
"rqBh6P9V06G/PS/fDnDDXYjDZr6vcdLPZfzNKITrfHNT/CzGHjyFs5pThF34k+zFRVTpzmgvUcAXyBmd",
"b0BFrj0axugbWvXWQdIvZVv2Dfa8Ldn3ZpbbZ+sKwLTNpcU3N17bJYJ1DcQSKi6M9EBLvc5Ww5WdEjQ3",
"Wmk5sl/FzTUWTlHlwcmYaNZmulZH7XINtO0A4y8m/ePyt6EZ5t5cKMYisSBGKHDKLFfhes37zoARGBy3",
"W/tm0rN0q/9c4oNg2JX8xL+6QLza5eNn8MVb1P1uVjS/YqWyUR1bkLl+6ubGGTbuSuwOO9ntr/XM1r1v",
"/jnn4Gs6HB+MHj8azdP08EH68PAHN/fR4P+VVelwZwChGaX2mxgcjg9HNCsWdD9YU/gz+a4z9vfOI17f",
"d1jFTs6BxjI+roVz8wQtGLwk7x00OaNWu1xUORVGulJVDp+hbFGyjFHFyLTiWeqCHMExYq4EVWQSrmqC",
"orEEUlV/AlE31pqGX0/mXE+I/QpsZFEfSgs96vNvgMKjjIFoDBt+xgBJmmVvZoOjv62/I6fO42O++jT8",
"uEZWWusDcNoUcV8QKbweFZVTMaohZrw1D8BB5W7i1lfvn96GdA3jxc6EcPwZQp079A3i3KffEI//nMnk",
"MuNK9zvgkEFZoxMtGVhuIZqRpSRhJahPoEWgm04a8cRaOBKHnFv5QML1vBC6XMXcH92XOk619eG/uJ9t",
"dQf7dg8RbZ1APXQY7dtDQp7b6xEPeTS/EjqVlcZ4RKd3WenJSVbWjMIbYlUTGmpBcyoukgVLLmWl1/vt",
"TuFl4l4OolncAkqWyyuWEppJMcfgXxd+sE1wWXMtPaCJW2g6C38hZDVfhC4RYBc08BwUnCWMaDnHLaZ8",
"NmMlmEzhBMFmab4mlCwkmKoyqvkVI+/evnJ+iIgNa0zOJDA3iHzBAJC3r4bmp4RqJqhm5HzwcUoV+7T3",
"UQov7alqNuMfmPp0PojJ7OaDJlqWWZQK2WEa7sUNsdato4CpgpF6juI1Vcph6inLWBIPpT7xXjcMBTbP",
"psxS9PdyqpyNukZhgy6BEAWyuaVZFzn9MDgaHOwfHI72H43275/dPzy6/+Do/sN/3T842t/vCj/drztB",
"glmGC0GHMitZSHLNwmayBE+146s1b2pdvh3ocxSkTNOUagrsP00hAJBmJxFzXoPxNjZTTrkuabkiuR3M",
"IfSYvDbbMNQ1Yx/C0CzrmMul2QXEUFSKizmZ0PF0nEwMWa/vkMHVS7ZqnVFRStjH0eC0KLlm5GXJ5wtt",
"mI1i5ZjlYIAdqNW0ZOL/ntowAlnO3RtWHj6FF8ip/t//64plgx44nVgj9TOvizTPPPSs5PQDz6t8cHR/",
"f384yLnAvyJultY18IP04P9pEEETPyxdVqznWy8rOPc8MGAMIxCJOQZMBSnQTjEczCjHHwtaKfjH3ytW",
"4WvwxcjLUQPcB6sYhs9VBtYjT5Oa0bo1Hvll9UEV3avxgAx8FoR9W5c3hkN9EXGpzTCc6GKX1XdKWpa9",
"bMI+BD7hg/RcwLUXKc31qBRExyGLM28hP2ApmfGMKWS6giVMKVquYgS8xeCiZuJ7zxx3PX5+L3Dbg+jm",
"HOVtRhxmdozJU240IYErdZ/EmLazv1ghwTHvWSlzv/U+VSkG6DOqLtVplee0XMVykvIiA8cWyaz0iHkp",
"Dupj8gzt7RjSYK3MLqzR/OQOCRyQ5vk4Ygq07tGthEqwr9oFbxHT1csI1b9VDPccMi2eG6374XCQB0S9",
"j0x+Gg4gW+ZiuoKMMsuuINrVIvpv3gLDRYNgeDpgScRvXRaIa/lYU7/78ZCHz+Y+L3mmjUJec5+h4yWv",
"jv/yomYl0Rh6OZsp1lxo1Bteg+rjDvlkakt63bejMCxzl10Fp9a+FW+ZrkqBRlGQQEBopo56cituwBZ2",
"0ZXa7vEAqfsRuC8QEVB/2zuFpoxr3qWIFzLgkBjuXI7AFlcVg2H9y6LSqVzG2Zo1CDyTYsbnVUmdlNrc",
"JFcvean020pssIhzBdI9R5HfENCZ+bCOdrLzkbISQWyFT0gC8YqSGVuSGTWkWA2JDQUXUowga89oIUm4",
"XmAyRgB1SrUPD54yiMnIC21IunlLL9jKitTiniZT1htsAXwEk7vSrXQ/WIUuqVAzVpKnJ8eQ1+DCY8c9",
"IR3AYl/JhMb1g+eeJQG/M9zM3DSYy3483mjgaM/S3t0wPOAY6tlT+6sLeYwgyIVeyiWN8LY3go2WdEVc",
"vCQGbUNWn1Qagh6lueQ2fwwyHjgkgJUMMgNzCLwxjHfy0cjBnyZWweQlZqw5kWQBOSLKeXpcargP1HU+",
"ojE5W8rImsA8aidNO7kCXvphdvlFRrXRZkbeZoM5myAu2EGmK7/oPkSDjzabSKxptQa0+3KL83papZyJ",
"ZsCrtU5ZBUOtIw5uGLWO9a0je2306TDG17QoDIzhlN2hELNlyAPTPruMY4p2ZMOrvzBWvK2EiCZ91yFg",
"y+DiWmdVTlfkkrHCECXhhMK4CJV35ukeaK0I9Ej1DY9PjLi0AtZoU1+oTcJe41xavD72IW0gkS8YmSy9",
"q4lNiNmKtWCHecd4fcwkAO+5NP8V7INuBF+hQ3dIJk0gTMjrd6dnRkOeQELfZKs4qxYgPdT6YBTDch/z",
"feyC9lt6rg2QX3+xWjlhkeFvPQfhq6UKgCbE0s0cxcbBbxfg/5bNDdsuWWo9zh1I0jQtmVI7lr+w9Dd+",
"0+RML2nJ1lzDnT28Lo3mwpuo1W4y9mcV0LAMwIEqLKLhADEcJJiHeWHjcjwUelYfO61TllQl1ysf8N+i",
"gNtGfq8L+T5luiqeKsWVpkKj8BnLlQiFPDk1sp3TwUHuMqMQP0yXWltD2gtIpqBbJNf2J5N8LUGtu4Uo",
"PEGce9brqTjFIBlrjLGuB16S05+eHjx8hNdeVfmQKP4PSFadriC42QhkNgeeZHZRLgujazVpGT1hNnDz",
"IvkZ1Gnb47lEIXRwNDh8ON1/8OR+cvB4un94eJjen00fPJwl+49/eELvHyR0/9H0fvrowX568PDRk8c/",
"7E9/2H+csof7D9LH+wdP2L4ZiP+DDY7uPzh4AH5inC2T8zkX83CqR4fTxwfJo8PpkwcHD2bp/cPpk8PH",
"+7Ppo/39R0/2f9hPDun9h4/vP05mhzR98ODg0eHD6f0fHieP6A9PHu4/flJPdfD4U9eQ4CByEqW25tdA",
"enSKkOXXYSa9G8cVy/C+FetXaZu4gIZT5ZUi9PmGYTfkWBCsr2F99cr5VexYGLvjQrrMg3O/HXL8/HyA",
"xiancvuAAZ+2QnEVoKtNrB1npLJqvgdFF0aGeu1h4YLR8fNJT6amRZkttWlc+0uesdOCJRsVaxx82Dym",
"zbep5v4xu655hla61qnEKgldAz2sW7qNGKA4W9DXvjm9oMJ6PZuRA1Q1BgW3jM2wpa6cRH2NyVkgXXw+",
"8m0RULLlkfij7hI4q4JRJ3VRpLyWVtlFB3Q4Lim2HPmyHg9NGfWI3hMbrSBDIytsktpwzOgYQGc+ds1t",
"rEmjBxsdNWY1drxhv7DbBPCvXC9qJ8xWoHZKeOK8lVHQD62YOiQpK2x0OtAR5xP5xs9mW9kzOI4e/07n",
"VENT+Lrj7fjWKnEp5FJA5EsmaYr6GAYPRc0CONhbXA1UjXHRi9cVPEDQaMCuV5a4IaHhVgSEW2Bv/Yff",
"PC/MZI1zNTwtELMpKYPPHEsZhkdpbROyed1ZeWXkjpc8Y0EEFCCa4ST2NfObS4io5fowi/i2cKC+mP4+",
"3AxahBP56/aFcSUg35+LNVgtsUk42l5iPP9dee6XIoRriV7J0tNNmlublSj4rOZYNDVCsdXpggg9aq2q",
"5Lza3z945O3BVjqrlMH8jqFZSztgZC4Upvw9sALUPdV0d0QzhwIL7w6WWG8Y/jQcZAGAdrS13IKrpHXq",
"Wa0h+603DCHNNUWxw2aHnFbTNaUuT5kAK77PvsMQOQUh13sq+HaCSYm2EJmWtgCRo5LBm+bhezn12Xjk",
"mRsT6ybNmQ6fo+oFpl6qLn3SsPs7k3OFbi3BmC0eUWQ84TpbuWmnDKPIwbFiHq2GfiNGi8C8E/euGUMK",
"jH34TktYT2PqmctUfS+n3wPvNq+bV+4pyGMEo7XmORufC+fjE1KjaWS6grRG0EosH6GaFKXUMpGZq/bj",
"oYW+GQSmL+cLGT3TUkLGjxm5GZPRvByy2EhlIrjwxtnKt63tFhvEVcRxlr/+MGqs0aBl8xj2SCXqHwxl",
"GO+cHCmLdSXg1m89EBP9MiBmqv4rKiH2gSJCHKgml1ykNidiaxj4yLAs+1lOIUg7y371Ti1bkICqy0zO",
"8WEYHBu+fkbncfdXIwMhWnertmgFBaq0rLGxKcFsE+vy+SGB9sHh7/8f+a9///0/fv/P3//H7//xX//+",
"+//8/T9////DHHaophDGfcAsoPUcDfYwcHdPzfbey6lCM879g8MxvARmlEpcXqBccxjg5MkvPxoULdTg",
"yIhVUKvTSDv3R/f3sRzfBSRosaXyJSAhNhhL9LEPmgmbyTMurGvIrORCVtqX4GmsD6fwK9yL79zWEuyM",
"V0qp145nC0RiZbqLmhMOMi6qD8H1A6/1yB6VDXzuRtyGSLAhVsQHvG5bBXxDnYzwrDfFyLhXa9v3VpE1",
"dThhD9Q64QFIa8ScqJXSLK8Dvu23rWpxEGaYyLnginXFK/tyHTNNSSaXrBwlVDFvtrRTuEXZEJNzPNDz",
"wZCcD5ZcpHKp8I+Ulksu8N+yYGKqUvMH08mYnPqpZF5QzX1l7x/lPUUmZSWAD/745s3p5E+krASZgH9V",
"ZiTlSkO8HwQ0GC5LffifK6rrF6nG5+KpcvInzYjZ0bCxD3LuYn7OB844aAuUo23GhWNDqcKihHwIqsj5",
"oCltuvHOBzXsc6mMPAFizSUjmim9l7JpNbcVEBVhVHGoNWilERcXit5rnpBUJlBjFhJdsqyxs2i5gL5E",
"FPPDxfblCockkQUPFcxJu2jd2Iw28SVsuwUPz+xfdTKHId4sJdz6x7EASSqZEvc0yalOML2DJrqimR+p",
"Y5g/w9K5IDqqdh1EwCOZpUFgXbPkebsMpS957UqDnIvjxgK5IjJHPjWsbWVQ62pVUKVatY476TxRoNs0",
"aE3nKMrZ2+dqmNXRt0H6+PFzH5pja7lY3o3qI9XEF42cMmJITFpleP3NUtBoCOEJGN0ly2BjBrtc9pVB",
"Q/eFX0kz/W0rKcq6X7t1YCJELiZnxdtYnLm6Gti4AuLblNOgnbnelSQbEj5mY5dw4cNkgjCp8W4lJb5k",
"84ubSJrEkN2L6erCRSvtErxsgw0ia90yhW2HShmQRqNlZfB0Q74iRqeJlU+VN/+X1skzNu5otzT5r98b",
"5KZyNR3p2eXEt83vbBfyiLUlCZuP+Mu0oQ+JLfezMUERkuSk7UESlPD5rIpOce+EITRgYG8V8xk2LO5d",
"TAlq9mycuSqz+MTv3r4K05Tr2QnXimUz78mUS5FJmm4TgVSX/PGniDl/sP++U/mMzCKfSKDkTI/aCUcx",
"/bGe8C7lDIW3+hpJQ2FaSFcnrpQmrJtdWqM75jvLRu3uutweiL9d7N+xXNFdIobXTUffkiK5mfpOal3F",
"MXzmSxtC4L0T5aSl0qiKIeZZMzfYG4FiwYlB7VEU9bCRiZHs/emB7U4WGDD8JyKtiaT1Ap8LqFTwHcg3",
"0kVcTxy9tdWzhNSEldRGtvpyDm2p3Szr+03ltbox6hkXtu2Ejb6FSIp7iiS+twEGmPMwfRvINXlzxcpl",
"yTVDWZ7LSkEhHxFUnXB5plHxIVZ87ZWc26JqngZgfTcnFbuWCGbRcCowIaNlxnuKUOsGCdyBSkSRq47m",
"jOoDJYOwlISBTgjKOxcYlY/jRJz96wJBP48KrLlkbtLYJar3uF3VEhs06vPmOokSxUWwx5ZkcELss06F",
"prUOme0MKv1jfX5gq6ax9jJnFCmF4/t1xSxo+JGzfIp4upVI36hS1l0AalfbDKAutyO5wVE1XEtB9Zto",
"TO2n34aRFPouO3TUtkazV9vUE+leml2VozaOrvcQu9H7bwfGdwceg9ribW3R9peRr9kVsaIqlpQMOKUc",
"CalHmmXZiIqVFCyMZD4aHI4P+mB/9DcXMGskt1lesLntBjOq24EMhoOcqySSCXrNUHO78I9f/ma15TOc",
"qenojE1hkbn/yE75XLxpH1aj8J21zNsDfHpyDE3TgpO4qCtuqSWdz1k5qvgNHUyrJF83waG/VldntTd/",
"TI6QxE+ms6I1p5QxVpxa21fEN20ee9uYC09ANdJlup0amIGLlokU0zC9fOPqSPm08ZSumnqaH9sQbFCU",
"xuRpUWSc2VqFmCcvzYcc7FaTlK7UhZxdLBm7nEC4H7zT/N287GoyR1YIMqEgBw9GC1mV5Kefjl6/rrOI",
"sa9OjbbhyIOjQS6JrgjEUYCbML0AqftocP+Ho/19TFqxSp9NaQa8cm/tP4nWSWlO0o2JpAkbKVbQEqN1",
"l3KUMehk5OrlWKhDcWK6Qr7I2GUPmMl354NcosdBV87Z8P2YvABrZ86oUOR8wK5YuTLjuao43d6Qfv+B",
"6AQA7ck8cqD5GC9A7gG1ebg2j/VjD5vQbIwbrHjNvdBUsz6d2iaUl2F63fZpPlGNOBhsq0WlLcLqI77o",
"kl6yLnJdJx9p+zCoxnehQ99WxzYSMKxrOKDKkBRzCJD8MxxopuwrcjYzyggYB9r1HmsE6i9sGcnux0p1",
"SLZqxdMmOdYhwVBM1pZRjtgG1EVG/7FaH3bUzJ+0/gnU5sIug0Cuag8LSiu1BmgVXkVmXHC16OsLOfyC",
"5zn0+1tzsn3WmD9TxZM1guf4M0rfLncpfbuLEf2rVJn9UhmCX6wG7DYVRH0FnpZmVfqc2mvYmbYv7Vrr",
"YzHFL1RYyFN0VlLhTUHZysZRrpy0QeeE68BxD1VZwLYx9q5BayYujMAgZ3XpeaN+EsXN31QwML50pYSO",
"Rtaoz2iGTiX58eQdwcANb+V58eKvL16M65q0P568G8FvESGh2Tl551Kams7H5JntSWu9ma0SR9RWmUfD",
"vU25oOBmL6lIZU5gQG8ism3yt/J4bms72aBbnNH5lqS/pvYeCVTHTmB3YBCheaKazi94CrrFg8P7B+mj",
"H5IRo4/S0YOHjx6Nnkxnj0bsyWz/yZQ9+CFh04ha4UcIRP3NHTPWif5uxLXQcWp+ZzG7qvBRY8inNVOj",
"kWQ7S1az/tPH6zqk4t1BIkaSM3SD+9MO2NQn1LIhLdmoQ3lo97igVSxB6J1iJRSQsAVzLcs4fj4kBVVq",
"KcvUl1AGtdrWCTH6j7Nf1mYNg3oAGOBshq/WO11oXQw+fYLmgejwg94YiQ4MIJ5WnzGaW1cVfqmO9vZm",
"LlyQy71ucQyMWSQvaZnbMFgImR4MBxlPmM3i8MTp1dVhZ/zlcjmei2osy/me/UbtzYtsdDjeHzMxXugc",
"iwlynTVWm/vS27Wyf3+8PwYFSRZM0IKDRcb8hHlIcDJ7tOB7V4d7Sbus0BwNJb4OxXEKPeR0s/4QyJiQ",
"AgKjHezvO6gyAd9To4NiBPjee+tBQ7zdMgC+OR8cXhPowmB15lNREAWdoGVWjNEzzQz1Wae7Jl7qv0HQ",
"HxCgeowXIi0kt1W/57a7emfATuVmA/koePcglGfPmVn6gP2Si/TPPqn8BDPHbgzc8d6OEXi/lJWoc8xB",
"PfbdNOFlG9j4hdaFxQ0i6zj17fKWRuJfllLMx63Tf8ltxLssSS5LRp69OnbNG9FZA3FviiwpRMyBDOW2",
"E0OKQqrISUECcuSogHf+WaarLwaNViGVCFhc20pZWl8fRB5h8RCJQWRY+ubm8ahRmKG70l+aF3eIi8Qw",
"NzjSGRfs7uHUX2nGweFKQ2y6DjK18NR6ba/q8V1P7fogNxIVTFMaBYHAa1C2kXb1VbH25Nbw858CMTE7",
"rcbIZvLaBna3wzi9yIipCVtKES8xe/uzjnyHwsWfho2xVjTPmmO15eJNCNI+iLfQGPaKxQWPrpyw9jSe",
"JglTyjeMjVRTjAxJwlQu3Ng98Om/KZh4enLsEtWyTC5texHXFH/PSpL2QCekoMmlOexz0X/ciumqGFFX",
"36ef7JzSKxYtKXQzhCc6VZRphmA1tJteIXq3kPJBpNNRCxkgAn3JprQonJEkNSrSrMqyun+ptpXGjFx5",
"90jJuzqkqCe1FSsOWasTNLkRsMMVmVUiwZsIhdg3oLdBiBhm91aO6sfBBufb++iyTT/tfXRO2E/rSFKD",
"GTa7bBsFnBvY2fINVoUL8llrxdk6qnZRcbo5vkaLj0wYOJP7J2xTr99ukJnG87Z3p5hOS2slWWeNfO+w",
"C1Mj09t8aU0CLtHbIKfP8kbb/4763brlNGqL9yZ/96OqT4LaHUvrCp//jaHX2ID6DOSsKwO0zQfknaoT",
"np3QTtN0hMxkTRYcklFfHJRNMeNrRqGli2EcseQRMqWqrt40LeVSNdLBro/x9R53x3FXX7uH80PyDbag",
"uhFW32hC1j3kn+XU5ivnXHfQ8yY1jjULArdYZSQ85J02S8yIaja8NWhOrgDaD+4f3LyMcOYpqk+HY5rO",
"IWsOZMo6ba75QjRpjmPP52xF0spXJ7MNjBKaLBzy+aHgPkhJMiOanItbFY/gAXElMZuUAHHMenagZqQs",
"O3cE6zpAQl0o+2Cx+MZwPzdzCJm9lJ1Lhar9FlcL9Nqve7+SYAnrrteDeJr+jhfCZ3saKop9OBZGoPzl",
"zRlmV9rGejZ9oU7P0wtZzRf/faH+KBcK0GrDdQLs9/s2I4EpDUqoLLk5cV17Z3nkmjW6oPWb5ZlOFj9m",
"ckobdSoghexmuUhfV/8tBJph/Mqdue56Lh0abg8Vq2hHuB65CPrIQTYxK69st9LI52rD8b2BqsHYHafO",
"QpoDoHuW0zq/nCo1wgZmuFX3r+YBQq83Zhu/3RC17G0rF7V9NhvLNWu9Y0M3aRuzja9NWhU2hAuJa04h",
"n9XcFNfI1FLER7dCEUuGaxIyaFtXE0J7LuM7Q61e0/ISVxqCbFhL466rSVJyzUpON2A8jJeb27bToMgD",
"nLRQJ1xhAQPDFABVHCW0VamgkJk5cfN73jz0LsmFQYtSou1xwfy7PuV9SpPLeSkrkY7PxS8S5qN4Zyft",
"VoUT4lVVCHsyX7GUVAXISkLzElz7UqSuLEhOET3Ra9cBD9bPXcmKsA8FS/QQqzswXpJJ3XNqUieyK1t7",
"1yhpGe6JQhNXmLVl2wRi8nfXCysuc0GnIVvO6IYIiG3HFTPhtQu7NknFnOnxbWs4jdZL/SwJoBp4Vmyc",
"GFaGgIoqfGaQGUQYIAW2ORF8eHdIAQgBvgSMAfx23K1ujjWDflwQKCZSoiQE+HZ5mhHf9j6a//5Cc7bW",
"NGQrpGxlGHID3hk7TbvOS6+Kgc/acojNpfACr4EpNKPxkNhwPkGuf7O1M5aViZ6L2uI01OAWgRa1bvmX",
"/G5UBIABKtsm16BSAUndGoj1VJ6h+PG6IPyIEWaftpLVtsJqX1+gH6c3xcD9to049RxJUEDHPGPydX10",
"yedzI63eLtF6J5AjspRAZkDXN4kBnQEnRRVgSLhIsipF5UhZbRr6fBl1QM6x2DCq3LZWkh/EsGsXpN8R",
"D8gv0jfYUJ0u39+tmP6+abD0mNWvf31VjLgV0yBH3a7LdFoKkutKvt7MhB+JlAQ5fH33cW/a7Jgfv5lv",
"oc9qo7/+bR7IjUhc9VZiCktVGPz9DmNOh7Y+xqpg3xuZK2gb732XHo5bepLd3aRJwgooj8WELjmzRi0g",
"K3aSu0ZUoJuwW62tR27ufACCXe/318Grm7voa5ELbClrEMyoVnOpEZ5BDSq4/XcJFZBGgQmomQxfl5Z3",
"ewA0SSUE01od129ZNXe4XurACBmPat4954ATp3I7WPvatjc09X0LSPkHNyk2j/oa5sXooI1G5P0IpJgO",
"yxX1+GZAEzipawL9wVmk24nN6e1xdQi2JA421zRZuol83hFVnjGilfLgoK8cl2u66ZbgIuHwex9H+5WJ",
"5hpk9ZJAvQULhma8y0YErbMj16Hnqa9d9cdGzkYJtx7UbCYYQ3SGNTNfC01PG8NdB0mbC7KYCp4rf9gu",
"q1n5Bh5e8v+DoHFzk7sgMeihG9nzGbz1bfBk2IvP54vLighjzlRYSk11JJ87JhZSu24oAEezLFx1Axu2",
"kffiO44j0XJB9Wgpqyy1/sFRKntxytucfl1Q/av56Fg//1YEPueR7JPzsFeCNetEbBAG+QIZClsYukxw",
"Z9OBRGgcBSIRXFVpF62BtUSHYGfK5NxGwfXKY2Aysh1X6lnq4dCwBPULhXd/pSSRwuUEZCs3BVdBa23r",
"fXDV6rErIgqestI9RqkvA4sQV7EDzp5rhreHBXDXMO1mD9kbivdpThLzQoUd41yMBrENNW/P+RTtARqL",
"8Xd9MKF9tm3WGbjDkV/vP7l5YulXQrOS0XRli4lbgeHBrfre8fQgBE3MIZCVTFQLonVbuUlwTRDlebIg",
"Uljz/q2xm6rFblpE6hm26KV1p1S8/mqVZ1xc+ugC6JaMEMD4Mo1ExQKlMqJLlgXWN+wDh9TCNsiyNd4T",
"mmX+gteRfDX9QKC2sx/sgihR4WWCxTQ6N9OS0bU0I2z+ty3lCE/2RqlIrAHltgTlK9CSaP/F2HqrqT02",
"6O0hQZwPD2IY1hIz79iGhdaVcqeuDPT3rJsjhzCwXWMx4aeQpVb24teM125sI8I/xYwz6qIVPdtoD+hb",
"zLkISOxTiauoyQ68q7QREPwSurcEht376HqYftr7CL/wf6xxqIftDGXJXGhtSwbcujstFE/tCozu1Z38",
"8MPOvEG5eNfY0VeKj8zqdr/NrHWz4t9u/OJ1WlhuaYi8U5coLGNWt9qMNl1tCJjBfVlHvD1G/nMj4zBm",
"VLFExZXNtD4H2/o+ZTNWEt/J1fXayWzG5vngYP+H84FHrDquDpQK8O/pqhROpK+3p7wch2GVvnVu58Ax",
"Eo9mSuIYSuZMCkZYpmCcun55bJmALQDABaNYUsCC8P8Z4TSjZ1SMnpt9jt7BAIMIDINGnTEYypLPuaAZ",
"zGnGh9Y9WCA9k2FBdd9imOugX5VtEcxDqm2VPFcDSxDK4Q1oSzXnGJO+aW9v7MJGL+3CBhtjlbaRZ2Si",
"mR4pXTKaNymE19SnXJj7PdycGP4M51CtvuTXsCs6MbRrUjzY/2HT6xYdG4hoSQ7G9z6OjlDaz406gGG4",
"U6aXzCK7BWcQDeS1dhsOMvN91WXZoTtedHa4DMrOw0gXIrzELnV6/a11N7C+ORbxXOyqnJEpMx/6+aer",
"xr1DiWLSe4WOiDmzia1gCNSlEZ18y9kUGzgQcAabT9HPd0gzXrfxEO7nTJYJn2YrkmTSNnH46ezshCRS",
"CAxkd82RJBSatITXVttUjfNihH2giSaK5sxKklq6RmoklZUR8vADBU1o8S1MNcTbVNcajJwAmcp01ctK",
"w5x2M0WtXXTBEkqOYF3c+2h713xab4CGcm1bhV36Vjh300BoS+5HHSdYUlXM5B21LDebMq0x20W+WHPy",
"e7bjx/rTdz2kvhUkcPtZhwvQFcrhQ09AU1tigg8XVBEBjVDIium7hU5hBEKnARdGaucMsxJw7xscYLYS",
"TCvswA053oB4GloLb4F8Z+bFu4N8mn3Qe0VGudixss5ZGzjfCl4FcVFUaTJjS9sxKEAybMm+FfUKP/Hj",
"uS5Ea7Fqu6CAoKnQrWLVl7dAdlq7ffNxAcgCv4HAAOzY5fPBwAzPZjOWaCfWQhdeHIEqsmRZ1s6OM98y",
"aitdLKqcCoUx0CCcggv5itNu9Y26lLW5I1DY3t0oDGiEi1XfqwnhQmlG27lkQXnw3pIuvpD3jbF0l47h",
"prp2GVWf19Fo0F2XQllfdgRVO+UbTmOnNGcC1ja13ecx0nq6iISOxzDK53pP07k5ifl22SR1ReZtFXFN",
"53Vix12OwA5L7kOJcrgMlcBizarRbtmHqZvdoW3fjKEgNb4+xhrMG0K214D1yyFyUE07TsaDzUdQ2Av9",
"4Wu9e92G782/ANsrqghMsQRbE6hfnjtuhKfNpm0B7JoGLYNptlulv05YoePuZHba0ndUoFce6uRtgywN",
"RBvabUKbEpuOTZu42UfINsS6+QNTt3LNXvXkK9SN5NV4TTbhMnyt/57FK9SCE/+rX4DdEP8WKR103a9D",
"WdAe6uJaoEmH8i6LIVGytvclNMusoe9SyCWEYb17d/z87lxCH8Ah2HLX64eSSBP14rct6Ma46cLdwm3r",
"u2p/ASu+W+umu6a2gpFNhnCfOlG34TCIlbHvAm/vo+3tsIPotZVK6Ye9+XTeTr1nizueR9lYvrsp8Tlt",
"aWn7CB5rvPmJzHPfdBh8mAmE3IIDxdZorQ0oS9/GhQsysS3EJqBcoQew+RKGXNj+RUPDxAvCNZnxUukx",
"eSpWaJHB18JWIcEwzmcIZL3yPbquJ3d+VZz60qRgDcfdNi146fuGbSOvkJRpaJPvj9jZdbe7+dtYlazO",
"322mddtHd1NCRLRB2F0wNt0RO1AvAm5nDXIYvRNSOoG619DZkKe/CTTsNPXqwcGujE6On6uGCaH2u7oe",
"4ETO/jlxNKiIbiCF0FALXngL2K+742fGWDFSQdfgTVyu2Wb4W2J5zZ1t05QDgloafZXXJSWzUKgTMvbl",
"3UTBDZTrq2LEjXHSTcjgcozbp3hty5Tv6/xV7VLXpE1GgJOls6w1+uFG0LzlxsDeeax0Hf/XyG/4ope3",
"b+783wb9/NZZnyRxq79V04yDBEv7xfWOO+XuxIi55TfMKx1FoSOj1UdiWF79pYogldH3RnI2WyN68bl4",
"M5tt5YK5e7C0HS6BxDZ6W/4N2mW2SnwGOi9VpG7PvRbgz2iWYbSis85oSTLrhnNlOsF8pxdsda9kZA6l",
"VOzw495TERsORdzo1bZT9F/qnGmaUk2/grE1bFb/h7jSW6Ph00ovmNAQFe/6zBlscKGUfdaCz8ZJDETW",
"EmawObgy4FS8PvAoxmqbCBsVjINTG3xt5ICVOu3GB3H0CqRCkv4v7jZW7Y4hLsPLd/kvMWtCrHqA0IsK",
"I3wz7SdhncNKBzdt8/ETxbSW2n+hPJ7uLKH+gSmPper23Jw9GcISEm9cUIQmhmxkLMXahJg4ZSnKqBkT",
"5dAFfKtc1Ak7lsqwcpTJhGZA4GimvjRVu2KN3VQx9xIEB63hs1Yet3HjN1cf1hree8O6odxa0K6kj1z9",
"Il09UJ+W6YtkBXaPB/uHX7B1H6JYL2KesNJ1TnnOBEfSafP346ZzDKGzLI8mml+hJZaBe9TViMoyuURf",
"hQWL3XrJ5wtNhFzaAL7D22Uw7iJRATlp6MAzUjisDjPLIGN9LqElu83MwAu346W17kHqxw+gsek2AU45",
"hbOMN7WJRtD1XxczJNrfvoVgVLuTvutoZSMucIkuMPBaVg07Vjf6NHZL6hwP1WzubzHJlaVU0uZz+bHr",
"0mq3bTD5TObUMOqqyyHRq4InEHtouw2BwFyUcl4ypYbQjsg1aJAlmVGeVSXbyGEcX1FMpA1HnQG3Gx2q",
"R7OSbb4pezldjfiorPrDSl/TlTWlVOKbSEp5TVd/Yax4ix7nb0w9w8BvK8bU2cuBxBy43gMGVVaC7JFL",
"xgrniq8DwMmbwtU+gkQ6yoUilKCrPZRJvVMm5n/vQeSORA/KXrCy1pq4qqPS16O2rHRR6VFRyrRK1gn6",
"hli+gZdP3Lt3gjlAzaq99wWb75pNPLTfFmL+tRKRD7ZMRAbpz6bYurYVD+7fv/mL9oqJuV744j1/Cjuf",
"pTzFfteGylJiQTCyn2BeuV3p4c2v9ISuIN8U2q7R0varenD/4W24EVRVFLI0B/WapZySs1VhPWaAYgQx",
"ygmTU58uXXcxDaO/Hhw8uZ0Oea5+A3JKIB1SYoekmbnYtlCcdUvrRSm1zpgtJ/eHkjwwT9sAOpdKk5Il",
"mL3uS9/BflEeCLK1OQAH+yaZj2tHCBMKa9dhDgVI7/aUzZf3FEn5nCkofts+Y/LMZ89DnNjJLz8CnH8+",
"efEjsahkBi0yKkQ8TmudwKMXVT4VlGdqryjZFWdLR5Z4iQX/HLUnSP2dGAQQLa8cNa/KbHA02BsERqg2",
"sTpuBkF12lo5TPHsAJJUuoUwfpZTZyYFGe3vFSu5Qb+6Xeew1U5h3KgCqSKDPj05bvY3DE1kMs8rgeIm",
"FNjotPRvO3AjE1hseO3XRKDVf293YWzGZLZh7kopM7eizmTgdIyUesH0eT8L8Ik6999C0PdcfC+nvqJZ",
"OIdN1//026f/EwAA//9lf+c1ZQ4BAA==",
}
// GetSwagger returns the content of the embedded swagger specification file

View File

@ -48,6 +48,8 @@ const (
// Defines values for BlenderPathSource.
const (
BlenderPathSourceEnvVariable BlenderPathSource = "env_variable"
BlenderPathSourceFileAssociation BlenderPathSource = "file_association"
BlenderPathSourceInputPath BlenderPathSource = "input_path"

View File

@ -40,6 +40,13 @@ export default class BlenderPathSource {
"input_path" = "input_path";
/**
* value: "env_variable"
* @const
*/
"env_variable" = "env_variable";
/**
* Returns a <code>BlenderPathSource</code> enum value from a Javascript object name.

View File

@ -115,6 +115,30 @@
<p v-else>Choose how a Worker should invoke the Blender command when performing a task:</p>
<fieldset v-if="autoFoundBlenders.length >= 1">
<label v-if="autoFoundBlenderEnvVariable" for="blender-env_variable">
<div>
<input
v-model="selectedBlender"
:value="autoFoundBlenderEnvVariable"
id="blender-env_variable"
name="blender"
type="radio" />
{{ sourceLabels[autoFoundBlenderEnvVariable.source] }}
</div>
<div class="setup-path-command">
<span class="path">
{{ autoFoundBlenderEnvVariable.path }}
</span>
<span
aria-label="Console output when running with --version"
class="command-preview"
data-microtip-position="top"
role="tooltip">
{{ autoFoundBlenderEnvVariable.cause }}
</span>
</div>
</label>
<label v-if="autoFoundBlenderPathEnvvar" for="blender-path_envvar">
<div>
<input
@ -236,6 +260,10 @@
>" as found on <code>$PATH</code> (currently "<code>{{ selectedBlender.path }}</code
>")
</dd>
<dd v-if="selectedBlender.source == 'env_variable'">
The command as found in <code>$FLAMENCO_BLENDER_PATH</code> (currently "<code>{{ selectedBlender.path }}</code
>")
</dd>
<dd v-if="selectedBlender.source == 'input_path'">
The command you provided: "<code>{{ selectedBlender.path }}</code
>"
@ -292,6 +320,7 @@ export default {
file_association: 'Blender that runs when you double-click a .blend file:',
path_envvar: 'Blender found on the $PATH environment:',
input_path: 'Another Blender executable:',
env_variable: 'Blender found in the $FLAMENCO_BLENDER_PATH environment variable:',
},
isConfirming: false,
isConfirmed: false,
@ -315,6 +344,9 @@ export default {
isConfigComplete() {
return this.isSharedStorageValid && this.isSelectedBlenderValid;
},
autoFoundBlenderEnvVariable() {
return this.autoFoundBlenders.find((b) => b.source === 'env_variable');
},
autoFoundBlenderPathEnvvar() {
return this.autoFoundBlenders.find((b) => b.source === 'path_envvar');
},