mirror of
https://github.com/ManimCommunity/manim.git
synced 2026-06-22 10:01:47 +00:00
Add interface to JS renderer (#465)
* Add interface to JS renderer * Update manim_directive.py * Add simple flag to get_style() * Change add_frames to add_frame * Update changelog.rst
This commit is contained in:
parent
de16dad1a7
commit
41f6f054e0
32 changed files with 3273 additions and 330 deletions
|
|
@ -32,6 +32,7 @@ Command line
|
|||
#. Re-implement GIF export with the :code:`-i` flag (using this flag outputs ONLY a .gif file, and no .mp4 file)
|
||||
#. Added a :code:`--verbose` flag
|
||||
#. You can save the logs to a file by using :code:`--log_to_file`
|
||||
#. Add experimental javascript rendering with :code:`--use_js_renderer`
|
||||
|
||||
|
||||
Config system
|
||||
|
|
@ -62,6 +63,7 @@ Mobjects, Scenes, and Animations
|
|||
#. Add a :code:`Variable` class for displaying text that continuously updates to reflect the value of a python variable.
|
||||
#. The ``Tex`` and ``MathTex`` objects allow you to specify a custom TexTemplate using the ``template`` keyword argument.
|
||||
#. :code:`VGroup` now supports printing the class names of contained mobjects and :code:`VDict` supports printing the internal dict of mobjects
|
||||
#. :code:`Scene` now renders when :code:`Scene.render()` is called rather than upon instantiation.
|
||||
#. :code:`ValueTracker` now supports increment using the `+=` operator (in addition to the already existing `increment_value` method)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -192,7 +192,7 @@ class ManimDirective(Directive):
|
|||
"from manim import *",
|
||||
*file_writer_config_code,
|
||||
*user_code,
|
||||
f"{clsname}()",
|
||||
f"{clsname}().render()",
|
||||
]
|
||||
exec("\n".join(code), globals())
|
||||
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ from .mobject.vector_field import *
|
|||
from .scene.graph_scene import *
|
||||
from .scene.moving_camera_scene import *
|
||||
from .scene.reconfigurable_scene import *
|
||||
from .scene.js_scene import *
|
||||
from .scene.scene import *
|
||||
from .scene.sample_space_scene import *
|
||||
from .scene.three_d_scene import *
|
||||
|
|
|
|||
|
|
@ -9,12 +9,17 @@ import importlib.util
|
|||
import types
|
||||
|
||||
from . import constants, logger, console, file_writer_config
|
||||
from .config.config import args
|
||||
from .config.config import camera_config, args
|
||||
from .config import cfg_subcmds
|
||||
from .utils.module_ops import (
|
||||
get_module,
|
||||
get_scene_classes_from_module,
|
||||
get_scenes_to_render,
|
||||
)
|
||||
from .scene.scene import Scene
|
||||
from .utils.sounds import play_error_sound, play_finish_sound
|
||||
from .utils.file_ops import open_file as open_media_file
|
||||
from . import constants
|
||||
from .grpc.impl import frame_server_impl
|
||||
|
||||
|
||||
def open_file_if_needed(file_writer):
|
||||
|
|
@ -50,104 +55,6 @@ def open_file_if_needed(file_writer):
|
|||
sys.stdout = curr_stdout
|
||||
|
||||
|
||||
def is_child_scene(obj, module):
|
||||
return (
|
||||
inspect.isclass(obj)
|
||||
and issubclass(obj, Scene)
|
||||
and obj != Scene
|
||||
and obj.__module__.startswith(module.__name__)
|
||||
)
|
||||
|
||||
|
||||
def prompt_user_for_choice(scene_classes):
|
||||
num_to_class = {}
|
||||
for count, scene_class in enumerate(scene_classes):
|
||||
count += 1 # start with 1 instead of 0
|
||||
name = scene_class.__name__
|
||||
console.print(f"{count}: {name}", style="logging.level.info")
|
||||
num_to_class[count] = scene_class
|
||||
try:
|
||||
user_input = console.input(
|
||||
f"[log.message] {constants.CHOOSE_NUMBER_MESSAGE} [/log.message]"
|
||||
)
|
||||
return [
|
||||
num_to_class[int(num_str)]
|
||||
for num_str in re.split(r"\s*,\s*", user_input.strip())
|
||||
]
|
||||
except KeyError:
|
||||
logger.error(constants.INVALID_NUMBER_MESSAGE)
|
||||
sys.exit(2)
|
||||
except EOFError:
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def get_scenes_to_render(scene_classes):
|
||||
if not scene_classes:
|
||||
logger.error(constants.NO_SCENE_MESSAGE)
|
||||
return []
|
||||
if file_writer_config["write_all"]:
|
||||
return scene_classes
|
||||
result = []
|
||||
for scene_name in file_writer_config["scene_names"]:
|
||||
found = False
|
||||
for scene_class in scene_classes:
|
||||
if scene_class.__name__ == scene_name:
|
||||
result.append(scene_class)
|
||||
found = True
|
||||
break
|
||||
if not found and (scene_name != ""):
|
||||
logger.error(constants.SCENE_NOT_FOUND_MESSAGE.format(scene_name))
|
||||
if result:
|
||||
return result
|
||||
return (
|
||||
[scene_classes[0]]
|
||||
if len(scene_classes) == 1
|
||||
else prompt_user_for_choice(scene_classes)
|
||||
)
|
||||
|
||||
|
||||
def get_scene_classes_from_module(module):
|
||||
return [
|
||||
member[1]
|
||||
for member in inspect.getmembers(module, lambda x: is_child_scene(x, module))
|
||||
]
|
||||
|
||||
|
||||
def get_module(file_name):
|
||||
if file_name == "-":
|
||||
# Since this feature is used for rapid testing, using Scene Caching would be a
|
||||
# hindrance in this case.
|
||||
file_writer_config["disable_caching"] = True
|
||||
module = types.ModuleType("input_scenes")
|
||||
logger.info(
|
||||
"Enter the animation's code & end with an EOF (CTRL+D on Linux/Unix, CTRL+Z on Windows):"
|
||||
)
|
||||
code = sys.stdin.read()
|
||||
if not code.startswith("from manim import"):
|
||||
logger.warning(
|
||||
"Didn't find an import statement for Manim. Importing automatically..."
|
||||
)
|
||||
code = "from manim import *\n" + code
|
||||
logger.info("Rendering animation from typed code...")
|
||||
try:
|
||||
exec(code, module.__dict__)
|
||||
return module
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to render scene: {str(e)}")
|
||||
sys.exit(2)
|
||||
else:
|
||||
if os.path.exists(file_name):
|
||||
if file_name[-3:] != ".py":
|
||||
raise Exception(f"{file_name} is not a valid Manim python script.")
|
||||
module_name = file_name[:-3].replace(os.sep, ".").split(".")[-1]
|
||||
spec = importlib.util.spec_from_file_location(module_name, file_name)
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(module)
|
||||
return module
|
||||
else:
|
||||
raise FileNotFoundError(f"{file_name} not found")
|
||||
|
||||
|
||||
def main():
|
||||
if hasattr(args, "subcommands"):
|
||||
if "cfg" in args.subcommands:
|
||||
|
|
@ -169,15 +76,19 @@ def main():
|
|||
sound_on = file_writer_config["sound"]
|
||||
for SceneClass in scene_classes_to_render:
|
||||
try:
|
||||
# By invoking, this renders the full scene
|
||||
scene = SceneClass()
|
||||
open_file_if_needed(scene.file_writer)
|
||||
if sound_on:
|
||||
play_finish_sound()
|
||||
if camera_config["use_js_renderer"]:
|
||||
frame_server_impl.get(SceneClass).start()
|
||||
else:
|
||||
scene = SceneClass()
|
||||
scene.render()
|
||||
open_file_if_needed(scene.file_writer)
|
||||
if sound_on:
|
||||
play_finish_sound()
|
||||
except Exception:
|
||||
print("\n\n")
|
||||
traceback.print_exc()
|
||||
print("\n\n")
|
||||
if not camera_config["use_js_renderer"]:
|
||||
if sound_on:
|
||||
play_error_sound()
|
||||
|
||||
|
|
|
|||
|
|
@ -104,12 +104,6 @@ class Camera(object):
|
|||
# corresponding class. If a Mobject is not an instance of a class in
|
||||
# this dict (or an instance of a class that inherits from a class in
|
||||
# this dict), then it cannot be rendered.
|
||||
self.display_funcs = {
|
||||
VMobject: self.display_multiple_vectorized_mobjects,
|
||||
PMobject: self.display_multiple_point_cloud_mobjects,
|
||||
AbstractImageMobject: self.display_multiple_image_mobjects,
|
||||
Mobject: lambda batch, pa: batch, # Do nothing
|
||||
}
|
||||
|
||||
self.init_background()
|
||||
self.resize_frame_shape()
|
||||
|
|
@ -149,6 +143,12 @@ class Camera(object):
|
|||
:exc:`TypeError`
|
||||
When mobject is not an instance of a class that can be rendered.
|
||||
"""
|
||||
self.display_funcs = {
|
||||
VMobject: self.display_multiple_vectorized_mobjects,
|
||||
PMobject: self.display_multiple_point_cloud_mobjects,
|
||||
AbstractImageMobject: self.display_multiple_image_mobjects,
|
||||
Mobject: lambda batch, pa: batch, # Do nothing
|
||||
}
|
||||
# We have to check each type in turn because we are dealing with
|
||||
# super classes. For example, if square = Square(), then
|
||||
# type(square) != VMobject, but isinstance(square, VMobject) == True.
|
||||
|
|
@ -358,6 +358,9 @@ class Camera(object):
|
|||
self.set_pixel_array(self.background)
|
||||
return self
|
||||
|
||||
def set_frame_to_background(self, background):
|
||||
self.set_pixel_array(background)
|
||||
|
||||
####
|
||||
|
||||
# TODO, it's weird that this is part of camera.
|
||||
|
|
|
|||
32
manim/camera/js_camera.py
Normal file
32
manim/camera/js_camera.py
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
from .camera import Camera
|
||||
import copy
|
||||
|
||||
|
||||
class JsCamera(Camera):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(self, **kwargs)
|
||||
self.serialized_frame = []
|
||||
self.pixel_array = None
|
||||
|
||||
def display_multiple_non_background_colored_vmobjects(self, vmobjects, _):
|
||||
for vmobject in vmobjects:
|
||||
# TODO: Store a proto instead of JSON.
|
||||
needs_redraw = False
|
||||
point_hash = hash(tuple(vmobject.points.flatten()))
|
||||
if vmobject.point_hash != point_hash:
|
||||
vmobject.point_hash = point_hash
|
||||
needs_redraw = True
|
||||
self.serialized_frame.append(
|
||||
{
|
||||
"points": vmobject.points.tolist(),
|
||||
"style": vmobject.get_style(simple=True),
|
||||
"id": id(vmobject),
|
||||
"needs_redraw": needs_redraw,
|
||||
}
|
||||
)
|
||||
|
||||
def reset(self):
|
||||
self.serialized_frame = []
|
||||
|
||||
def set_frame_to_background(self, background):
|
||||
self.serialized_frame = copy.deepcopy(background)
|
||||
|
|
@ -112,6 +112,14 @@ def _parse_config(config_parser, args):
|
|||
background_color = colour.Color(default["background_color"])
|
||||
config["background_color"] = background_color
|
||||
|
||||
config["use_js_renderer"] = args.use_js_renderer or default.getboolean(
|
||||
"use_js_renderer"
|
||||
)
|
||||
|
||||
config["js_renderer_path"] = args.js_renderer_path or default.get(
|
||||
"js_renderer_path"
|
||||
)
|
||||
|
||||
# Set the rest of the frame properties
|
||||
config["frame_height"] = 8.0
|
||||
config["frame_width"] = (
|
||||
|
|
@ -151,6 +159,8 @@ if _from_command_line():
|
|||
if not (hasattr(args, "subcommands")):
|
||||
_init_dirs(file_writer_config)
|
||||
config = _parse_config(config_parser, args)
|
||||
if config["use_js_renderer"]:
|
||||
file_writer_config["disable_caching"] = True
|
||||
camera_config = config
|
||||
|
||||
# Set the different loggers
|
||||
|
|
|
|||
|
|
@ -391,6 +391,18 @@ def _parse_cli(arg_list, input=True):
|
|||
"the rendering at the second value",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--use_js_renderer",
|
||||
help="Render animations using the javascript frontend",
|
||||
action="store_const",
|
||||
const=True,
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--js_renderer_path",
|
||||
help="Path to the javascript frontend",
|
||||
)
|
||||
|
||||
# Specify the manim.cfg file
|
||||
parser.add_argument(
|
||||
"--config_file",
|
||||
|
|
|
|||
|
|
@ -78,6 +78,21 @@ media_dir = ./media
|
|||
# --log_dir (by default "/logs", that will be put inside the media dir)
|
||||
log_dir = logs
|
||||
|
||||
# # --video_dir
|
||||
# video_dir = %(MEDIA_DIR)s/videos
|
||||
|
||||
# # --tex_dir
|
||||
# tex_dir = %(MEDIA_DIR)s/Tex
|
||||
|
||||
# # --text_dir
|
||||
# text_dir = %(MEDIA_DIR)s/texts
|
||||
|
||||
# --use_js_renderer
|
||||
use_js_renderer = False
|
||||
|
||||
# --js_renderer_path
|
||||
js_renderer_path =
|
||||
|
||||
# If the -t (--transparent) flag is used, these will be replaced with the
|
||||
# values specified in the [TRANSPARENT] section later in this file.
|
||||
png_mode = RGB
|
||||
|
|
|
|||
|
|
@ -120,3 +120,9 @@ FFMPEG_VERBOSITY_MAP = {
|
|||
"CRITICAL": "fatal",
|
||||
}
|
||||
VERBOSITY_CHOICES = FFMPEG_VERBOSITY_MAP.keys()
|
||||
JS_RENDERER_INFO = (
|
||||
"The Electron frontend to Manim is hosted at "
|
||||
"https://github.com/ManimCommunity/manim-renderer. After cloning and building it, "
|
||||
"you can either start it prior to running Manim or specify the path to the "
|
||||
"executable with the --js_renderer_path flag."
|
||||
)
|
||||
|
|
|
|||
0
manim/grpc/__init__.py
Normal file
0
manim/grpc/__init__.py
Normal file
6
manim/grpc/gen/__init__.py
Normal file
6
manim/grpc/gen/__init__.py
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
# https://github.com/protocolbuffers/protobuf/issues/1491#issuecomment-547504972
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
sys.path.append(str(Path(__file__).parent))
|
||||
743
manim/grpc/gen/frameserver_pb2.py
Normal file
743
manim/grpc/gen/frameserver_pb2.py
Normal file
|
|
@ -0,0 +1,743 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
# source: frameserver.proto
|
||||
|
||||
from google.protobuf import descriptor as _descriptor
|
||||
from google.protobuf import message as _message
|
||||
from google.protobuf import reflection as _reflection
|
||||
from google.protobuf import symbol_database as _symbol_database
|
||||
|
||||
# @@protoc_insertion_point(imports)
|
||||
|
||||
_sym_db = _symbol_database.Default()
|
||||
|
||||
|
||||
DESCRIPTOR = _descriptor.FileDescriptor(
|
||||
name="frameserver.proto",
|
||||
package="frameserver",
|
||||
syntax="proto3",
|
||||
serialized_options=None,
|
||||
serialized_pb=b'\n\x11\x66rameserver.proto\x12\x0b\x66rameserver"A\n\x0c\x46rameRequest\x12\x17\n\x0f\x61nimation_index\x18\x01 \x01(\x03\x12\x18\n\x10\x61nimation_offset\x18\x02 \x01(\x02"u\n\x05Style\x12\x12\n\nfill_color\x18\x01 \x01(\t\x12\x14\n\x0c\x66ill_opacity\x18\x02 \x01(\x02\x12\x14\n\x0cstroke_color\x18\x03 \x01(\t\x12\x16\n\x0estroke_opacity\x18\x04 \x01(\x02\x12\x14\n\x0cstroke_width\x18\x05 \x01(\x02"(\n\x05Point\x12\t\n\x01x\x18\x01 \x01(\x02\x12\t\n\x01y\x18\x02 \x01(\x02\x12\t\n\x01z\x18\x03 \x01(\x02"v\n\x0bMobjectData\x12\n\n\x02id\x18\x01 \x01(\x03\x12"\n\x06points\x18\x02 \x03(\x0b\x32\x12.frameserver.Point\x12!\n\x05style\x18\x03 \x01(\x0b\x32\x12.frameserver.Style\x12\x14\n\x0cneeds_redraw\x18\x04 \x01(\x08"\xb0\x01\n\rFrameResponse\x12*\n\x08mobjects\x18\x01 \x03(\x0b\x32\x18.frameserver.MobjectData\x12\x15\n\rframe_pending\x18\x02 \x01(\x08\x12\x1a\n\x12\x61nimation_finished\x18\x03 \x01(\x08\x12\x16\n\x0escene_finished\x18\x04 \x01(\x08\x12\x10\n\x08\x64uration\x18\x05 \x01(\x02\x12\x16\n\x0e\x61nimation_name\x18\x06 \x01(\t"\x17\n\x15RendererStatusRequest",\n\x16RendererStatusResponse\x12\x12\n\nscene_name\x18\x01 \x01(\t"\x16\n\x14SceneLocationRequest"\x17\n\x15SceneLocationResponse2\x8f\x02\n\x0b\x46rameServer\x12G\n\x0eGetFrameAtTime\x12\x19.frameserver.FrameRequest\x1a\x1a.frameserver.FrameResponse\x12Y\n\x0eRendererStatus\x12".frameserver.RendererStatusRequest\x1a#.frameserver.RendererStatusResponse\x12\\\n\x13UpdateSceneLocation\x12!.frameserver.SceneLocationRequest\x1a".frameserver.SceneLocationResponseb\x06proto3',
|
||||
)
|
||||
|
||||
|
||||
_FRAMEREQUEST = _descriptor.Descriptor(
|
||||
name="FrameRequest",
|
||||
full_name="frameserver.FrameRequest",
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name="animation_index",
|
||||
full_name="frameserver.FrameRequest.animation_index",
|
||||
index=0,
|
||||
number=1,
|
||||
type=3,
|
||||
cpp_type=2,
|
||||
label=1,
|
||||
has_default_value=False,
|
||||
default_value=0,
|
||||
message_type=None,
|
||||
enum_type=None,
|
||||
containing_type=None,
|
||||
is_extension=False,
|
||||
extension_scope=None,
|
||||
serialized_options=None,
|
||||
file=DESCRIPTOR,
|
||||
),
|
||||
_descriptor.FieldDescriptor(
|
||||
name="animation_offset",
|
||||
full_name="frameserver.FrameRequest.animation_offset",
|
||||
index=1,
|
||||
number=2,
|
||||
type=2,
|
||||
cpp_type=6,
|
||||
label=1,
|
||||
has_default_value=False,
|
||||
default_value=float(0),
|
||||
message_type=None,
|
||||
enum_type=None,
|
||||
containing_type=None,
|
||||
is_extension=False,
|
||||
extension_scope=None,
|
||||
serialized_options=None,
|
||||
file=DESCRIPTOR,
|
||||
),
|
||||
],
|
||||
extensions=[],
|
||||
nested_types=[],
|
||||
enum_types=[],
|
||||
serialized_options=None,
|
||||
is_extendable=False,
|
||||
syntax="proto3",
|
||||
extension_ranges=[],
|
||||
oneofs=[],
|
||||
serialized_start=34,
|
||||
serialized_end=99,
|
||||
)
|
||||
|
||||
|
||||
_STYLE = _descriptor.Descriptor(
|
||||
name="Style",
|
||||
full_name="frameserver.Style",
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name="fill_color",
|
||||
full_name="frameserver.Style.fill_color",
|
||||
index=0,
|
||||
number=1,
|
||||
type=9,
|
||||
cpp_type=9,
|
||||
label=1,
|
||||
has_default_value=False,
|
||||
default_value=b"".decode("utf-8"),
|
||||
message_type=None,
|
||||
enum_type=None,
|
||||
containing_type=None,
|
||||
is_extension=False,
|
||||
extension_scope=None,
|
||||
serialized_options=None,
|
||||
file=DESCRIPTOR,
|
||||
),
|
||||
_descriptor.FieldDescriptor(
|
||||
name="fill_opacity",
|
||||
full_name="frameserver.Style.fill_opacity",
|
||||
index=1,
|
||||
number=2,
|
||||
type=2,
|
||||
cpp_type=6,
|
||||
label=1,
|
||||
has_default_value=False,
|
||||
default_value=float(0),
|
||||
message_type=None,
|
||||
enum_type=None,
|
||||
containing_type=None,
|
||||
is_extension=False,
|
||||
extension_scope=None,
|
||||
serialized_options=None,
|
||||
file=DESCRIPTOR,
|
||||
),
|
||||
_descriptor.FieldDescriptor(
|
||||
name="stroke_color",
|
||||
full_name="frameserver.Style.stroke_color",
|
||||
index=2,
|
||||
number=3,
|
||||
type=9,
|
||||
cpp_type=9,
|
||||
label=1,
|
||||
has_default_value=False,
|
||||
default_value=b"".decode("utf-8"),
|
||||
message_type=None,
|
||||
enum_type=None,
|
||||
containing_type=None,
|
||||
is_extension=False,
|
||||
extension_scope=None,
|
||||
serialized_options=None,
|
||||
file=DESCRIPTOR,
|
||||
),
|
||||
_descriptor.FieldDescriptor(
|
||||
name="stroke_opacity",
|
||||
full_name="frameserver.Style.stroke_opacity",
|
||||
index=3,
|
||||
number=4,
|
||||
type=2,
|
||||
cpp_type=6,
|
||||
label=1,
|
||||
has_default_value=False,
|
||||
default_value=float(0),
|
||||
message_type=None,
|
||||
enum_type=None,
|
||||
containing_type=None,
|
||||
is_extension=False,
|
||||
extension_scope=None,
|
||||
serialized_options=None,
|
||||
file=DESCRIPTOR,
|
||||
),
|
||||
_descriptor.FieldDescriptor(
|
||||
name="stroke_width",
|
||||
full_name="frameserver.Style.stroke_width",
|
||||
index=4,
|
||||
number=5,
|
||||
type=2,
|
||||
cpp_type=6,
|
||||
label=1,
|
||||
has_default_value=False,
|
||||
default_value=float(0),
|
||||
message_type=None,
|
||||
enum_type=None,
|
||||
containing_type=None,
|
||||
is_extension=False,
|
||||
extension_scope=None,
|
||||
serialized_options=None,
|
||||
file=DESCRIPTOR,
|
||||
),
|
||||
],
|
||||
extensions=[],
|
||||
nested_types=[],
|
||||
enum_types=[],
|
||||
serialized_options=None,
|
||||
is_extendable=False,
|
||||
syntax="proto3",
|
||||
extension_ranges=[],
|
||||
oneofs=[],
|
||||
serialized_start=101,
|
||||
serialized_end=218,
|
||||
)
|
||||
|
||||
|
||||
_POINT = _descriptor.Descriptor(
|
||||
name="Point",
|
||||
full_name="frameserver.Point",
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name="x",
|
||||
full_name="frameserver.Point.x",
|
||||
index=0,
|
||||
number=1,
|
||||
type=2,
|
||||
cpp_type=6,
|
||||
label=1,
|
||||
has_default_value=False,
|
||||
default_value=float(0),
|
||||
message_type=None,
|
||||
enum_type=None,
|
||||
containing_type=None,
|
||||
is_extension=False,
|
||||
extension_scope=None,
|
||||
serialized_options=None,
|
||||
file=DESCRIPTOR,
|
||||
),
|
||||
_descriptor.FieldDescriptor(
|
||||
name="y",
|
||||
full_name="frameserver.Point.y",
|
||||
index=1,
|
||||
number=2,
|
||||
type=2,
|
||||
cpp_type=6,
|
||||
label=1,
|
||||
has_default_value=False,
|
||||
default_value=float(0),
|
||||
message_type=None,
|
||||
enum_type=None,
|
||||
containing_type=None,
|
||||
is_extension=False,
|
||||
extension_scope=None,
|
||||
serialized_options=None,
|
||||
file=DESCRIPTOR,
|
||||
),
|
||||
_descriptor.FieldDescriptor(
|
||||
name="z",
|
||||
full_name="frameserver.Point.z",
|
||||
index=2,
|
||||
number=3,
|
||||
type=2,
|
||||
cpp_type=6,
|
||||
label=1,
|
||||
has_default_value=False,
|
||||
default_value=float(0),
|
||||
message_type=None,
|
||||
enum_type=None,
|
||||
containing_type=None,
|
||||
is_extension=False,
|
||||
extension_scope=None,
|
||||
serialized_options=None,
|
||||
file=DESCRIPTOR,
|
||||
),
|
||||
],
|
||||
extensions=[],
|
||||
nested_types=[],
|
||||
enum_types=[],
|
||||
serialized_options=None,
|
||||
is_extendable=False,
|
||||
syntax="proto3",
|
||||
extension_ranges=[],
|
||||
oneofs=[],
|
||||
serialized_start=220,
|
||||
serialized_end=260,
|
||||
)
|
||||
|
||||
|
||||
_MOBJECTDATA = _descriptor.Descriptor(
|
||||
name="MobjectData",
|
||||
full_name="frameserver.MobjectData",
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name="id",
|
||||
full_name="frameserver.MobjectData.id",
|
||||
index=0,
|
||||
number=1,
|
||||
type=3,
|
||||
cpp_type=2,
|
||||
label=1,
|
||||
has_default_value=False,
|
||||
default_value=0,
|
||||
message_type=None,
|
||||
enum_type=None,
|
||||
containing_type=None,
|
||||
is_extension=False,
|
||||
extension_scope=None,
|
||||
serialized_options=None,
|
||||
file=DESCRIPTOR,
|
||||
),
|
||||
_descriptor.FieldDescriptor(
|
||||
name="points",
|
||||
full_name="frameserver.MobjectData.points",
|
||||
index=1,
|
||||
number=2,
|
||||
type=11,
|
||||
cpp_type=10,
|
||||
label=3,
|
||||
has_default_value=False,
|
||||
default_value=[],
|
||||
message_type=None,
|
||||
enum_type=None,
|
||||
containing_type=None,
|
||||
is_extension=False,
|
||||
extension_scope=None,
|
||||
serialized_options=None,
|
||||
file=DESCRIPTOR,
|
||||
),
|
||||
_descriptor.FieldDescriptor(
|
||||
name="style",
|
||||
full_name="frameserver.MobjectData.style",
|
||||
index=2,
|
||||
number=3,
|
||||
type=11,
|
||||
cpp_type=10,
|
||||
label=1,
|
||||
has_default_value=False,
|
||||
default_value=None,
|
||||
message_type=None,
|
||||
enum_type=None,
|
||||
containing_type=None,
|
||||
is_extension=False,
|
||||
extension_scope=None,
|
||||
serialized_options=None,
|
||||
file=DESCRIPTOR,
|
||||
),
|
||||
_descriptor.FieldDescriptor(
|
||||
name="needs_redraw",
|
||||
full_name="frameserver.MobjectData.needs_redraw",
|
||||
index=3,
|
||||
number=4,
|
||||
type=8,
|
||||
cpp_type=7,
|
||||
label=1,
|
||||
has_default_value=False,
|
||||
default_value=False,
|
||||
message_type=None,
|
||||
enum_type=None,
|
||||
containing_type=None,
|
||||
is_extension=False,
|
||||
extension_scope=None,
|
||||
serialized_options=None,
|
||||
file=DESCRIPTOR,
|
||||
),
|
||||
],
|
||||
extensions=[],
|
||||
nested_types=[],
|
||||
enum_types=[],
|
||||
serialized_options=None,
|
||||
is_extendable=False,
|
||||
syntax="proto3",
|
||||
extension_ranges=[],
|
||||
oneofs=[],
|
||||
serialized_start=262,
|
||||
serialized_end=380,
|
||||
)
|
||||
|
||||
|
||||
_FRAMERESPONSE = _descriptor.Descriptor(
|
||||
name="FrameResponse",
|
||||
full_name="frameserver.FrameResponse",
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name="mobjects",
|
||||
full_name="frameserver.FrameResponse.mobjects",
|
||||
index=0,
|
||||
number=1,
|
||||
type=11,
|
||||
cpp_type=10,
|
||||
label=3,
|
||||
has_default_value=False,
|
||||
default_value=[],
|
||||
message_type=None,
|
||||
enum_type=None,
|
||||
containing_type=None,
|
||||
is_extension=False,
|
||||
extension_scope=None,
|
||||
serialized_options=None,
|
||||
file=DESCRIPTOR,
|
||||
),
|
||||
_descriptor.FieldDescriptor(
|
||||
name="frame_pending",
|
||||
full_name="frameserver.FrameResponse.frame_pending",
|
||||
index=1,
|
||||
number=2,
|
||||
type=8,
|
||||
cpp_type=7,
|
||||
label=1,
|
||||
has_default_value=False,
|
||||
default_value=False,
|
||||
message_type=None,
|
||||
enum_type=None,
|
||||
containing_type=None,
|
||||
is_extension=False,
|
||||
extension_scope=None,
|
||||
serialized_options=None,
|
||||
file=DESCRIPTOR,
|
||||
),
|
||||
_descriptor.FieldDescriptor(
|
||||
name="animation_finished",
|
||||
full_name="frameserver.FrameResponse.animation_finished",
|
||||
index=2,
|
||||
number=3,
|
||||
type=8,
|
||||
cpp_type=7,
|
||||
label=1,
|
||||
has_default_value=False,
|
||||
default_value=False,
|
||||
message_type=None,
|
||||
enum_type=None,
|
||||
containing_type=None,
|
||||
is_extension=False,
|
||||
extension_scope=None,
|
||||
serialized_options=None,
|
||||
file=DESCRIPTOR,
|
||||
),
|
||||
_descriptor.FieldDescriptor(
|
||||
name="scene_finished",
|
||||
full_name="frameserver.FrameResponse.scene_finished",
|
||||
index=3,
|
||||
number=4,
|
||||
type=8,
|
||||
cpp_type=7,
|
||||
label=1,
|
||||
has_default_value=False,
|
||||
default_value=False,
|
||||
message_type=None,
|
||||
enum_type=None,
|
||||
containing_type=None,
|
||||
is_extension=False,
|
||||
extension_scope=None,
|
||||
serialized_options=None,
|
||||
file=DESCRIPTOR,
|
||||
),
|
||||
_descriptor.FieldDescriptor(
|
||||
name="duration",
|
||||
full_name="frameserver.FrameResponse.duration",
|
||||
index=4,
|
||||
number=5,
|
||||
type=2,
|
||||
cpp_type=6,
|
||||
label=1,
|
||||
has_default_value=False,
|
||||
default_value=float(0),
|
||||
message_type=None,
|
||||
enum_type=None,
|
||||
containing_type=None,
|
||||
is_extension=False,
|
||||
extension_scope=None,
|
||||
serialized_options=None,
|
||||
file=DESCRIPTOR,
|
||||
),
|
||||
_descriptor.FieldDescriptor(
|
||||
name="animation_name",
|
||||
full_name="frameserver.FrameResponse.animation_name",
|
||||
index=5,
|
||||
number=6,
|
||||
type=9,
|
||||
cpp_type=9,
|
||||
label=1,
|
||||
has_default_value=False,
|
||||
default_value=b"".decode("utf-8"),
|
||||
message_type=None,
|
||||
enum_type=None,
|
||||
containing_type=None,
|
||||
is_extension=False,
|
||||
extension_scope=None,
|
||||
serialized_options=None,
|
||||
file=DESCRIPTOR,
|
||||
),
|
||||
],
|
||||
extensions=[],
|
||||
nested_types=[],
|
||||
enum_types=[],
|
||||
serialized_options=None,
|
||||
is_extendable=False,
|
||||
syntax="proto3",
|
||||
extension_ranges=[],
|
||||
oneofs=[],
|
||||
serialized_start=383,
|
||||
serialized_end=559,
|
||||
)
|
||||
|
||||
|
||||
_RENDERERSTATUSREQUEST = _descriptor.Descriptor(
|
||||
name="RendererStatusRequest",
|
||||
full_name="frameserver.RendererStatusRequest",
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[],
|
||||
extensions=[],
|
||||
nested_types=[],
|
||||
enum_types=[],
|
||||
serialized_options=None,
|
||||
is_extendable=False,
|
||||
syntax="proto3",
|
||||
extension_ranges=[],
|
||||
oneofs=[],
|
||||
serialized_start=561,
|
||||
serialized_end=584,
|
||||
)
|
||||
|
||||
|
||||
_RENDERERSTATUSRESPONSE = _descriptor.Descriptor(
|
||||
name="RendererStatusResponse",
|
||||
full_name="frameserver.RendererStatusResponse",
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name="scene_name",
|
||||
full_name="frameserver.RendererStatusResponse.scene_name",
|
||||
index=0,
|
||||
number=1,
|
||||
type=9,
|
||||
cpp_type=9,
|
||||
label=1,
|
||||
has_default_value=False,
|
||||
default_value=b"".decode("utf-8"),
|
||||
message_type=None,
|
||||
enum_type=None,
|
||||
containing_type=None,
|
||||
is_extension=False,
|
||||
extension_scope=None,
|
||||
serialized_options=None,
|
||||
file=DESCRIPTOR,
|
||||
),
|
||||
],
|
||||
extensions=[],
|
||||
nested_types=[],
|
||||
enum_types=[],
|
||||
serialized_options=None,
|
||||
is_extendable=False,
|
||||
syntax="proto3",
|
||||
extension_ranges=[],
|
||||
oneofs=[],
|
||||
serialized_start=586,
|
||||
serialized_end=630,
|
||||
)
|
||||
|
||||
|
||||
_SCENELOCATIONREQUEST = _descriptor.Descriptor(
|
||||
name="SceneLocationRequest",
|
||||
full_name="frameserver.SceneLocationRequest",
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[],
|
||||
extensions=[],
|
||||
nested_types=[],
|
||||
enum_types=[],
|
||||
serialized_options=None,
|
||||
is_extendable=False,
|
||||
syntax="proto3",
|
||||
extension_ranges=[],
|
||||
oneofs=[],
|
||||
serialized_start=632,
|
||||
serialized_end=654,
|
||||
)
|
||||
|
||||
|
||||
_SCENELOCATIONRESPONSE = _descriptor.Descriptor(
|
||||
name="SceneLocationResponse",
|
||||
full_name="frameserver.SceneLocationResponse",
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[],
|
||||
extensions=[],
|
||||
nested_types=[],
|
||||
enum_types=[],
|
||||
serialized_options=None,
|
||||
is_extendable=False,
|
||||
syntax="proto3",
|
||||
extension_ranges=[],
|
||||
oneofs=[],
|
||||
serialized_start=656,
|
||||
serialized_end=679,
|
||||
)
|
||||
|
||||
_MOBJECTDATA.fields_by_name["points"].message_type = _POINT
|
||||
_MOBJECTDATA.fields_by_name["style"].message_type = _STYLE
|
||||
_FRAMERESPONSE.fields_by_name["mobjects"].message_type = _MOBJECTDATA
|
||||
DESCRIPTOR.message_types_by_name["FrameRequest"] = _FRAMEREQUEST
|
||||
DESCRIPTOR.message_types_by_name["Style"] = _STYLE
|
||||
DESCRIPTOR.message_types_by_name["Point"] = _POINT
|
||||
DESCRIPTOR.message_types_by_name["MobjectData"] = _MOBJECTDATA
|
||||
DESCRIPTOR.message_types_by_name["FrameResponse"] = _FRAMERESPONSE
|
||||
DESCRIPTOR.message_types_by_name["RendererStatusRequest"] = _RENDERERSTATUSREQUEST
|
||||
DESCRIPTOR.message_types_by_name["RendererStatusResponse"] = _RENDERERSTATUSRESPONSE
|
||||
DESCRIPTOR.message_types_by_name["SceneLocationRequest"] = _SCENELOCATIONREQUEST
|
||||
DESCRIPTOR.message_types_by_name["SceneLocationResponse"] = _SCENELOCATIONRESPONSE
|
||||
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
|
||||
|
||||
FrameRequest = _reflection.GeneratedProtocolMessageType(
|
||||
"FrameRequest",
|
||||
(_message.Message,),
|
||||
{
|
||||
"DESCRIPTOR": _FRAMEREQUEST,
|
||||
"__module__": "frameserver_pb2"
|
||||
# @@protoc_insertion_point(class_scope:frameserver.FrameRequest)
|
||||
},
|
||||
)
|
||||
_sym_db.RegisterMessage(FrameRequest)
|
||||
|
||||
Style = _reflection.GeneratedProtocolMessageType(
|
||||
"Style",
|
||||
(_message.Message,),
|
||||
{
|
||||
"DESCRIPTOR": _STYLE,
|
||||
"__module__": "frameserver_pb2"
|
||||
# @@protoc_insertion_point(class_scope:frameserver.Style)
|
||||
},
|
||||
)
|
||||
_sym_db.RegisterMessage(Style)
|
||||
|
||||
Point = _reflection.GeneratedProtocolMessageType(
|
||||
"Point",
|
||||
(_message.Message,),
|
||||
{
|
||||
"DESCRIPTOR": _POINT,
|
||||
"__module__": "frameserver_pb2"
|
||||
# @@protoc_insertion_point(class_scope:frameserver.Point)
|
||||
},
|
||||
)
|
||||
_sym_db.RegisterMessage(Point)
|
||||
|
||||
MobjectData = _reflection.GeneratedProtocolMessageType(
|
||||
"MobjectData",
|
||||
(_message.Message,),
|
||||
{
|
||||
"DESCRIPTOR": _MOBJECTDATA,
|
||||
"__module__": "frameserver_pb2"
|
||||
# @@protoc_insertion_point(class_scope:frameserver.MobjectData)
|
||||
},
|
||||
)
|
||||
_sym_db.RegisterMessage(MobjectData)
|
||||
|
||||
FrameResponse = _reflection.GeneratedProtocolMessageType(
|
||||
"FrameResponse",
|
||||
(_message.Message,),
|
||||
{
|
||||
"DESCRIPTOR": _FRAMERESPONSE,
|
||||
"__module__": "frameserver_pb2"
|
||||
# @@protoc_insertion_point(class_scope:frameserver.FrameResponse)
|
||||
},
|
||||
)
|
||||
_sym_db.RegisterMessage(FrameResponse)
|
||||
|
||||
RendererStatusRequest = _reflection.GeneratedProtocolMessageType(
|
||||
"RendererStatusRequest",
|
||||
(_message.Message,),
|
||||
{
|
||||
"DESCRIPTOR": _RENDERERSTATUSREQUEST,
|
||||
"__module__": "frameserver_pb2"
|
||||
# @@protoc_insertion_point(class_scope:frameserver.RendererStatusRequest)
|
||||
},
|
||||
)
|
||||
_sym_db.RegisterMessage(RendererStatusRequest)
|
||||
|
||||
RendererStatusResponse = _reflection.GeneratedProtocolMessageType(
|
||||
"RendererStatusResponse",
|
||||
(_message.Message,),
|
||||
{
|
||||
"DESCRIPTOR": _RENDERERSTATUSRESPONSE,
|
||||
"__module__": "frameserver_pb2"
|
||||
# @@protoc_insertion_point(class_scope:frameserver.RendererStatusResponse)
|
||||
},
|
||||
)
|
||||
_sym_db.RegisterMessage(RendererStatusResponse)
|
||||
|
||||
SceneLocationRequest = _reflection.GeneratedProtocolMessageType(
|
||||
"SceneLocationRequest",
|
||||
(_message.Message,),
|
||||
{
|
||||
"DESCRIPTOR": _SCENELOCATIONREQUEST,
|
||||
"__module__": "frameserver_pb2"
|
||||
# @@protoc_insertion_point(class_scope:frameserver.SceneLocationRequest)
|
||||
},
|
||||
)
|
||||
_sym_db.RegisterMessage(SceneLocationRequest)
|
||||
|
||||
SceneLocationResponse = _reflection.GeneratedProtocolMessageType(
|
||||
"SceneLocationResponse",
|
||||
(_message.Message,),
|
||||
{
|
||||
"DESCRIPTOR": _SCENELOCATIONRESPONSE,
|
||||
"__module__": "frameserver_pb2"
|
||||
# @@protoc_insertion_point(class_scope:frameserver.SceneLocationResponse)
|
||||
},
|
||||
)
|
||||
_sym_db.RegisterMessage(SceneLocationResponse)
|
||||
|
||||
|
||||
_FRAMESERVER = _descriptor.ServiceDescriptor(
|
||||
name="FrameServer",
|
||||
full_name="frameserver.FrameServer",
|
||||
file=DESCRIPTOR,
|
||||
index=0,
|
||||
serialized_options=None,
|
||||
serialized_start=682,
|
||||
serialized_end=953,
|
||||
methods=[
|
||||
_descriptor.MethodDescriptor(
|
||||
name="GetFrameAtTime",
|
||||
full_name="frameserver.FrameServer.GetFrameAtTime",
|
||||
index=0,
|
||||
containing_service=None,
|
||||
input_type=_FRAMEREQUEST,
|
||||
output_type=_FRAMERESPONSE,
|
||||
serialized_options=None,
|
||||
),
|
||||
_descriptor.MethodDescriptor(
|
||||
name="RendererStatus",
|
||||
full_name="frameserver.FrameServer.RendererStatus",
|
||||
index=1,
|
||||
containing_service=None,
|
||||
input_type=_RENDERERSTATUSREQUEST,
|
||||
output_type=_RENDERERSTATUSRESPONSE,
|
||||
serialized_options=None,
|
||||
),
|
||||
_descriptor.MethodDescriptor(
|
||||
name="UpdateSceneLocation",
|
||||
full_name="frameserver.FrameServer.UpdateSceneLocation",
|
||||
index=2,
|
||||
containing_service=None,
|
||||
input_type=_SCENELOCATIONREQUEST,
|
||||
output_type=_SCENELOCATIONRESPONSE,
|
||||
serialized_options=None,
|
||||
),
|
||||
],
|
||||
)
|
||||
_sym_db.RegisterServiceDescriptor(_FRAMESERVER)
|
||||
|
||||
DESCRIPTOR.services_by_name["FrameServer"] = _FRAMESERVER
|
||||
|
||||
# @@protoc_insertion_point(module_scope)
|
||||
164
manim/grpc/gen/frameserver_pb2_grpc.py
Normal file
164
manim/grpc/gen/frameserver_pb2_grpc.py
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
|
||||
import grpc
|
||||
|
||||
import frameserver_pb2 as frameserver__pb2
|
||||
|
||||
|
||||
class FrameServerStub(object):
|
||||
"""Missing associated documentation comment in .proto file"""
|
||||
|
||||
def __init__(self, channel):
|
||||
"""Constructor.
|
||||
|
||||
Args:
|
||||
channel: A grpc.Channel.
|
||||
"""
|
||||
self.GetFrameAtTime = channel.unary_unary(
|
||||
"/frameserver.FrameServer/GetFrameAtTime",
|
||||
request_serializer=frameserver__pb2.FrameRequest.SerializeToString,
|
||||
response_deserializer=frameserver__pb2.FrameResponse.FromString,
|
||||
)
|
||||
self.RendererStatus = channel.unary_unary(
|
||||
"/frameserver.FrameServer/RendererStatus",
|
||||
request_serializer=frameserver__pb2.RendererStatusRequest.SerializeToString,
|
||||
response_deserializer=frameserver__pb2.RendererStatusResponse.FromString,
|
||||
)
|
||||
self.UpdateSceneLocation = channel.unary_unary(
|
||||
"/frameserver.FrameServer/UpdateSceneLocation",
|
||||
request_serializer=frameserver__pb2.SceneLocationRequest.SerializeToString,
|
||||
response_deserializer=frameserver__pb2.SceneLocationResponse.FromString,
|
||||
)
|
||||
|
||||
|
||||
class FrameServerServicer(object):
|
||||
"""Missing associated documentation comment in .proto file"""
|
||||
|
||||
def GetFrameAtTime(self, request, context):
|
||||
"""Updates the scene to the specified animation offset and returns a
|
||||
serialization of the frame at that time.
|
||||
"""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details("Method not implemented!")
|
||||
raise NotImplementedError("Method not implemented!")
|
||||
|
||||
def RendererStatus(self, request, context):
|
||||
"""Used to signal to the renderer that manim is running."""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details("Method not implemented!")
|
||||
raise NotImplementedError("Method not implemented!")
|
||||
|
||||
def UpdateSceneLocation(self, request, context):
|
||||
"""Missing associated documentation comment in .proto file"""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details("Method not implemented!")
|
||||
raise NotImplementedError("Method not implemented!")
|
||||
|
||||
|
||||
def add_FrameServerServicer_to_server(servicer, server):
|
||||
rpc_method_handlers = {
|
||||
"GetFrameAtTime": grpc.unary_unary_rpc_method_handler(
|
||||
servicer.GetFrameAtTime,
|
||||
request_deserializer=frameserver__pb2.FrameRequest.FromString,
|
||||
response_serializer=frameserver__pb2.FrameResponse.SerializeToString,
|
||||
),
|
||||
"RendererStatus": grpc.unary_unary_rpc_method_handler(
|
||||
servicer.RendererStatus,
|
||||
request_deserializer=frameserver__pb2.RendererStatusRequest.FromString,
|
||||
response_serializer=frameserver__pb2.RendererStatusResponse.SerializeToString,
|
||||
),
|
||||
"UpdateSceneLocation": grpc.unary_unary_rpc_method_handler(
|
||||
servicer.UpdateSceneLocation,
|
||||
request_deserializer=frameserver__pb2.SceneLocationRequest.FromString,
|
||||
response_serializer=frameserver__pb2.SceneLocationResponse.SerializeToString,
|
||||
),
|
||||
}
|
||||
generic_handler = grpc.method_handlers_generic_handler(
|
||||
"frameserver.FrameServer", rpc_method_handlers
|
||||
)
|
||||
server.add_generic_rpc_handlers((generic_handler,))
|
||||
|
||||
|
||||
# This class is part of an EXPERIMENTAL API.
|
||||
class FrameServer(object):
|
||||
"""Missing associated documentation comment in .proto file"""
|
||||
|
||||
@staticmethod
|
||||
def GetFrameAtTime(
|
||||
request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None,
|
||||
):
|
||||
return grpc.experimental.unary_unary(
|
||||
request,
|
||||
target,
|
||||
"/frameserver.FrameServer/GetFrameAtTime",
|
||||
frameserver__pb2.FrameRequest.SerializeToString,
|
||||
frameserver__pb2.FrameResponse.FromString,
|
||||
options,
|
||||
channel_credentials,
|
||||
call_credentials,
|
||||
compression,
|
||||
wait_for_ready,
|
||||
timeout,
|
||||
metadata,
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def RendererStatus(
|
||||
request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None,
|
||||
):
|
||||
return grpc.experimental.unary_unary(
|
||||
request,
|
||||
target,
|
||||
"/frameserver.FrameServer/RendererStatus",
|
||||
frameserver__pb2.RendererStatusRequest.SerializeToString,
|
||||
frameserver__pb2.RendererStatusResponse.FromString,
|
||||
options,
|
||||
channel_credentials,
|
||||
call_credentials,
|
||||
compression,
|
||||
wait_for_ready,
|
||||
timeout,
|
||||
metadata,
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def UpdateSceneLocation(
|
||||
request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None,
|
||||
):
|
||||
return grpc.experimental.unary_unary(
|
||||
request,
|
||||
target,
|
||||
"/frameserver.FrameServer/UpdateSceneLocation",
|
||||
frameserver__pb2.SceneLocationRequest.SerializeToString,
|
||||
frameserver__pb2.SceneLocationResponse.FromString,
|
||||
options,
|
||||
channel_credentials,
|
||||
call_credentials,
|
||||
compression,
|
||||
wait_for_ready,
|
||||
timeout,
|
||||
metadata,
|
||||
)
|
||||
550
manim/grpc/gen/renderserver_pb2.py
Normal file
550
manim/grpc/gen/renderserver_pb2.py
Normal file
|
|
@ -0,0 +1,550 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
# source: renderserver.proto
|
||||
|
||||
from google.protobuf import descriptor as _descriptor
|
||||
from google.protobuf import message as _message
|
||||
from google.protobuf import reflection as _reflection
|
||||
from google.protobuf import symbol_database as _symbol_database
|
||||
|
||||
# @@protoc_insertion_point(imports)
|
||||
|
||||
_sym_db = _symbol_database.Default()
|
||||
|
||||
|
||||
DESCRIPTOR = _descriptor.FileDescriptor(
|
||||
name="renderserver.proto",
|
||||
package="renderserver",
|
||||
syntax="proto3",
|
||||
serialized_options=None,
|
||||
serialized_pb=b'\n\x12renderserver.proto\x12\x0crenderserver"\x0e\n\x0c\x45mptyRequest"\x0f\n\rEmptyResponse"\x1f\n\x0fNewSceneRequest\x12\x0c\n\x04name\x18\x01 \x01(\t"\x12\n\x10NewSceneResponse"+\n\tAnimation\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x10\n\x08\x64uration\x18\x02 \x01(\x02"\x18\n\x16\x41nimationStatusRequest"\x19\n\x17\x41nimationStatusResponse"m\n\x12ManimStatusRequest\x12\x12\n\nscene_name\x18\x01 \x01(\t\x12\x16\n\x0escene_finished\x18\x02 \x01(\x08\x12+\n\nanimations\x18\x03 \x03(\x0b\x32\x17.renderserver.Animation"\x15\n\x13ManimStatusResponse"\x14\n\x12UpdateSceneRequest"\x15\n\x13UpdateSceneResponse2\x94\x03\n\x0cRenderServer\x12J\n\x0f\x41nimationStatus\x12\x1a.renderserver.EmptyRequest\x1a\x1b.renderserver.EmptyResponse\x12R\n\x0bManimStatus\x12 .renderserver.ManimStatusRequest\x1a!.renderserver.ManimStatusResponse\x12R\n\x0bUpdateScene\x12 .renderserver.UpdateSceneRequest\x1a!.renderserver.UpdateSceneResponse\x12\x46\n\x08NewScene\x12\x1d.renderserver.NewSceneRequest\x1a\x1b.renderserver.EmptyResponse\x12H\n\rSceneFinished\x12\x1a.renderserver.EmptyRequest\x1a\x1b.renderserver.EmptyResponseb\x06proto3',
|
||||
)
|
||||
|
||||
|
||||
_EMPTYREQUEST = _descriptor.Descriptor(
|
||||
name="EmptyRequest",
|
||||
full_name="renderserver.EmptyRequest",
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[],
|
||||
extensions=[],
|
||||
nested_types=[],
|
||||
enum_types=[],
|
||||
serialized_options=None,
|
||||
is_extendable=False,
|
||||
syntax="proto3",
|
||||
extension_ranges=[],
|
||||
oneofs=[],
|
||||
serialized_start=36,
|
||||
serialized_end=50,
|
||||
)
|
||||
|
||||
|
||||
_EMPTYRESPONSE = _descriptor.Descriptor(
|
||||
name="EmptyResponse",
|
||||
full_name="renderserver.EmptyResponse",
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[],
|
||||
extensions=[],
|
||||
nested_types=[],
|
||||
enum_types=[],
|
||||
serialized_options=None,
|
||||
is_extendable=False,
|
||||
syntax="proto3",
|
||||
extension_ranges=[],
|
||||
oneofs=[],
|
||||
serialized_start=52,
|
||||
serialized_end=67,
|
||||
)
|
||||
|
||||
|
||||
_NEWSCENEREQUEST = _descriptor.Descriptor(
|
||||
name="NewSceneRequest",
|
||||
full_name="renderserver.NewSceneRequest",
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name="name",
|
||||
full_name="renderserver.NewSceneRequest.name",
|
||||
index=0,
|
||||
number=1,
|
||||
type=9,
|
||||
cpp_type=9,
|
||||
label=1,
|
||||
has_default_value=False,
|
||||
default_value=b"".decode("utf-8"),
|
||||
message_type=None,
|
||||
enum_type=None,
|
||||
containing_type=None,
|
||||
is_extension=False,
|
||||
extension_scope=None,
|
||||
serialized_options=None,
|
||||
file=DESCRIPTOR,
|
||||
),
|
||||
],
|
||||
extensions=[],
|
||||
nested_types=[],
|
||||
enum_types=[],
|
||||
serialized_options=None,
|
||||
is_extendable=False,
|
||||
syntax="proto3",
|
||||
extension_ranges=[],
|
||||
oneofs=[],
|
||||
serialized_start=69,
|
||||
serialized_end=100,
|
||||
)
|
||||
|
||||
|
||||
_NEWSCENERESPONSE = _descriptor.Descriptor(
|
||||
name="NewSceneResponse",
|
||||
full_name="renderserver.NewSceneResponse",
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[],
|
||||
extensions=[],
|
||||
nested_types=[],
|
||||
enum_types=[],
|
||||
serialized_options=None,
|
||||
is_extendable=False,
|
||||
syntax="proto3",
|
||||
extension_ranges=[],
|
||||
oneofs=[],
|
||||
serialized_start=102,
|
||||
serialized_end=120,
|
||||
)
|
||||
|
||||
|
||||
_ANIMATION = _descriptor.Descriptor(
|
||||
name="Animation",
|
||||
full_name="renderserver.Animation",
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name="name",
|
||||
full_name="renderserver.Animation.name",
|
||||
index=0,
|
||||
number=1,
|
||||
type=9,
|
||||
cpp_type=9,
|
||||
label=1,
|
||||
has_default_value=False,
|
||||
default_value=b"".decode("utf-8"),
|
||||
message_type=None,
|
||||
enum_type=None,
|
||||
containing_type=None,
|
||||
is_extension=False,
|
||||
extension_scope=None,
|
||||
serialized_options=None,
|
||||
file=DESCRIPTOR,
|
||||
),
|
||||
_descriptor.FieldDescriptor(
|
||||
name="duration",
|
||||
full_name="renderserver.Animation.duration",
|
||||
index=1,
|
||||
number=2,
|
||||
type=2,
|
||||
cpp_type=6,
|
||||
label=1,
|
||||
has_default_value=False,
|
||||
default_value=float(0),
|
||||
message_type=None,
|
||||
enum_type=None,
|
||||
containing_type=None,
|
||||
is_extension=False,
|
||||
extension_scope=None,
|
||||
serialized_options=None,
|
||||
file=DESCRIPTOR,
|
||||
),
|
||||
],
|
||||
extensions=[],
|
||||
nested_types=[],
|
||||
enum_types=[],
|
||||
serialized_options=None,
|
||||
is_extendable=False,
|
||||
syntax="proto3",
|
||||
extension_ranges=[],
|
||||
oneofs=[],
|
||||
serialized_start=122,
|
||||
serialized_end=165,
|
||||
)
|
||||
|
||||
|
||||
_ANIMATIONSTATUSREQUEST = _descriptor.Descriptor(
|
||||
name="AnimationStatusRequest",
|
||||
full_name="renderserver.AnimationStatusRequest",
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[],
|
||||
extensions=[],
|
||||
nested_types=[],
|
||||
enum_types=[],
|
||||
serialized_options=None,
|
||||
is_extendable=False,
|
||||
syntax="proto3",
|
||||
extension_ranges=[],
|
||||
oneofs=[],
|
||||
serialized_start=167,
|
||||
serialized_end=191,
|
||||
)
|
||||
|
||||
|
||||
_ANIMATIONSTATUSRESPONSE = _descriptor.Descriptor(
|
||||
name="AnimationStatusResponse",
|
||||
full_name="renderserver.AnimationStatusResponse",
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[],
|
||||
extensions=[],
|
||||
nested_types=[],
|
||||
enum_types=[],
|
||||
serialized_options=None,
|
||||
is_extendable=False,
|
||||
syntax="proto3",
|
||||
extension_ranges=[],
|
||||
oneofs=[],
|
||||
serialized_start=193,
|
||||
serialized_end=218,
|
||||
)
|
||||
|
||||
|
||||
_MANIMSTATUSREQUEST = _descriptor.Descriptor(
|
||||
name="ManimStatusRequest",
|
||||
full_name="renderserver.ManimStatusRequest",
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name="scene_name",
|
||||
full_name="renderserver.ManimStatusRequest.scene_name",
|
||||
index=0,
|
||||
number=1,
|
||||
type=9,
|
||||
cpp_type=9,
|
||||
label=1,
|
||||
has_default_value=False,
|
||||
default_value=b"".decode("utf-8"),
|
||||
message_type=None,
|
||||
enum_type=None,
|
||||
containing_type=None,
|
||||
is_extension=False,
|
||||
extension_scope=None,
|
||||
serialized_options=None,
|
||||
file=DESCRIPTOR,
|
||||
),
|
||||
_descriptor.FieldDescriptor(
|
||||
name="scene_finished",
|
||||
full_name="renderserver.ManimStatusRequest.scene_finished",
|
||||
index=1,
|
||||
number=2,
|
||||
type=8,
|
||||
cpp_type=7,
|
||||
label=1,
|
||||
has_default_value=False,
|
||||
default_value=False,
|
||||
message_type=None,
|
||||
enum_type=None,
|
||||
containing_type=None,
|
||||
is_extension=False,
|
||||
extension_scope=None,
|
||||
serialized_options=None,
|
||||
file=DESCRIPTOR,
|
||||
),
|
||||
_descriptor.FieldDescriptor(
|
||||
name="animations",
|
||||
full_name="renderserver.ManimStatusRequest.animations",
|
||||
index=2,
|
||||
number=3,
|
||||
type=11,
|
||||
cpp_type=10,
|
||||
label=3,
|
||||
has_default_value=False,
|
||||
default_value=[],
|
||||
message_type=None,
|
||||
enum_type=None,
|
||||
containing_type=None,
|
||||
is_extension=False,
|
||||
extension_scope=None,
|
||||
serialized_options=None,
|
||||
file=DESCRIPTOR,
|
||||
),
|
||||
],
|
||||
extensions=[],
|
||||
nested_types=[],
|
||||
enum_types=[],
|
||||
serialized_options=None,
|
||||
is_extendable=False,
|
||||
syntax="proto3",
|
||||
extension_ranges=[],
|
||||
oneofs=[],
|
||||
serialized_start=220,
|
||||
serialized_end=329,
|
||||
)
|
||||
|
||||
|
||||
_MANIMSTATUSRESPONSE = _descriptor.Descriptor(
|
||||
name="ManimStatusResponse",
|
||||
full_name="renderserver.ManimStatusResponse",
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[],
|
||||
extensions=[],
|
||||
nested_types=[],
|
||||
enum_types=[],
|
||||
serialized_options=None,
|
||||
is_extendable=False,
|
||||
syntax="proto3",
|
||||
extension_ranges=[],
|
||||
oneofs=[],
|
||||
serialized_start=331,
|
||||
serialized_end=352,
|
||||
)
|
||||
|
||||
|
||||
_UPDATESCENEREQUEST = _descriptor.Descriptor(
|
||||
name="UpdateSceneRequest",
|
||||
full_name="renderserver.UpdateSceneRequest",
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[],
|
||||
extensions=[],
|
||||
nested_types=[],
|
||||
enum_types=[],
|
||||
serialized_options=None,
|
||||
is_extendable=False,
|
||||
syntax="proto3",
|
||||
extension_ranges=[],
|
||||
oneofs=[],
|
||||
serialized_start=354,
|
||||
serialized_end=374,
|
||||
)
|
||||
|
||||
|
||||
_UPDATESCENERESPONSE = _descriptor.Descriptor(
|
||||
name="UpdateSceneResponse",
|
||||
full_name="renderserver.UpdateSceneResponse",
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[],
|
||||
extensions=[],
|
||||
nested_types=[],
|
||||
enum_types=[],
|
||||
serialized_options=None,
|
||||
is_extendable=False,
|
||||
syntax="proto3",
|
||||
extension_ranges=[],
|
||||
oneofs=[],
|
||||
serialized_start=376,
|
||||
serialized_end=397,
|
||||
)
|
||||
|
||||
_MANIMSTATUSREQUEST.fields_by_name["animations"].message_type = _ANIMATION
|
||||
DESCRIPTOR.message_types_by_name["EmptyRequest"] = _EMPTYREQUEST
|
||||
DESCRIPTOR.message_types_by_name["EmptyResponse"] = _EMPTYRESPONSE
|
||||
DESCRIPTOR.message_types_by_name["NewSceneRequest"] = _NEWSCENEREQUEST
|
||||
DESCRIPTOR.message_types_by_name["NewSceneResponse"] = _NEWSCENERESPONSE
|
||||
DESCRIPTOR.message_types_by_name["Animation"] = _ANIMATION
|
||||
DESCRIPTOR.message_types_by_name["AnimationStatusRequest"] = _ANIMATIONSTATUSREQUEST
|
||||
DESCRIPTOR.message_types_by_name["AnimationStatusResponse"] = _ANIMATIONSTATUSRESPONSE
|
||||
DESCRIPTOR.message_types_by_name["ManimStatusRequest"] = _MANIMSTATUSREQUEST
|
||||
DESCRIPTOR.message_types_by_name["ManimStatusResponse"] = _MANIMSTATUSRESPONSE
|
||||
DESCRIPTOR.message_types_by_name["UpdateSceneRequest"] = _UPDATESCENEREQUEST
|
||||
DESCRIPTOR.message_types_by_name["UpdateSceneResponse"] = _UPDATESCENERESPONSE
|
||||
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
|
||||
|
||||
EmptyRequest = _reflection.GeneratedProtocolMessageType(
|
||||
"EmptyRequest",
|
||||
(_message.Message,),
|
||||
{
|
||||
"DESCRIPTOR": _EMPTYREQUEST,
|
||||
"__module__": "renderserver_pb2"
|
||||
# @@protoc_insertion_point(class_scope:renderserver.EmptyRequest)
|
||||
},
|
||||
)
|
||||
_sym_db.RegisterMessage(EmptyRequest)
|
||||
|
||||
EmptyResponse = _reflection.GeneratedProtocolMessageType(
|
||||
"EmptyResponse",
|
||||
(_message.Message,),
|
||||
{
|
||||
"DESCRIPTOR": _EMPTYRESPONSE,
|
||||
"__module__": "renderserver_pb2"
|
||||
# @@protoc_insertion_point(class_scope:renderserver.EmptyResponse)
|
||||
},
|
||||
)
|
||||
_sym_db.RegisterMessage(EmptyResponse)
|
||||
|
||||
NewSceneRequest = _reflection.GeneratedProtocolMessageType(
|
||||
"NewSceneRequest",
|
||||
(_message.Message,),
|
||||
{
|
||||
"DESCRIPTOR": _NEWSCENEREQUEST,
|
||||
"__module__": "renderserver_pb2"
|
||||
# @@protoc_insertion_point(class_scope:renderserver.NewSceneRequest)
|
||||
},
|
||||
)
|
||||
_sym_db.RegisterMessage(NewSceneRequest)
|
||||
|
||||
NewSceneResponse = _reflection.GeneratedProtocolMessageType(
|
||||
"NewSceneResponse",
|
||||
(_message.Message,),
|
||||
{
|
||||
"DESCRIPTOR": _NEWSCENERESPONSE,
|
||||
"__module__": "renderserver_pb2"
|
||||
# @@protoc_insertion_point(class_scope:renderserver.NewSceneResponse)
|
||||
},
|
||||
)
|
||||
_sym_db.RegisterMessage(NewSceneResponse)
|
||||
|
||||
Animation = _reflection.GeneratedProtocolMessageType(
|
||||
"Animation",
|
||||
(_message.Message,),
|
||||
{
|
||||
"DESCRIPTOR": _ANIMATION,
|
||||
"__module__": "renderserver_pb2"
|
||||
# @@protoc_insertion_point(class_scope:renderserver.Animation)
|
||||
},
|
||||
)
|
||||
_sym_db.RegisterMessage(Animation)
|
||||
|
||||
AnimationStatusRequest = _reflection.GeneratedProtocolMessageType(
|
||||
"AnimationStatusRequest",
|
||||
(_message.Message,),
|
||||
{
|
||||
"DESCRIPTOR": _ANIMATIONSTATUSREQUEST,
|
||||
"__module__": "renderserver_pb2"
|
||||
# @@protoc_insertion_point(class_scope:renderserver.AnimationStatusRequest)
|
||||
},
|
||||
)
|
||||
_sym_db.RegisterMessage(AnimationStatusRequest)
|
||||
|
||||
AnimationStatusResponse = _reflection.GeneratedProtocolMessageType(
|
||||
"AnimationStatusResponse",
|
||||
(_message.Message,),
|
||||
{
|
||||
"DESCRIPTOR": _ANIMATIONSTATUSRESPONSE,
|
||||
"__module__": "renderserver_pb2"
|
||||
# @@protoc_insertion_point(class_scope:renderserver.AnimationStatusResponse)
|
||||
},
|
||||
)
|
||||
_sym_db.RegisterMessage(AnimationStatusResponse)
|
||||
|
||||
ManimStatusRequest = _reflection.GeneratedProtocolMessageType(
|
||||
"ManimStatusRequest",
|
||||
(_message.Message,),
|
||||
{
|
||||
"DESCRIPTOR": _MANIMSTATUSREQUEST,
|
||||
"__module__": "renderserver_pb2"
|
||||
# @@protoc_insertion_point(class_scope:renderserver.ManimStatusRequest)
|
||||
},
|
||||
)
|
||||
_sym_db.RegisterMessage(ManimStatusRequest)
|
||||
|
||||
ManimStatusResponse = _reflection.GeneratedProtocolMessageType(
|
||||
"ManimStatusResponse",
|
||||
(_message.Message,),
|
||||
{
|
||||
"DESCRIPTOR": _MANIMSTATUSRESPONSE,
|
||||
"__module__": "renderserver_pb2"
|
||||
# @@protoc_insertion_point(class_scope:renderserver.ManimStatusResponse)
|
||||
},
|
||||
)
|
||||
_sym_db.RegisterMessage(ManimStatusResponse)
|
||||
|
||||
UpdateSceneRequest = _reflection.GeneratedProtocolMessageType(
|
||||
"UpdateSceneRequest",
|
||||
(_message.Message,),
|
||||
{
|
||||
"DESCRIPTOR": _UPDATESCENEREQUEST,
|
||||
"__module__": "renderserver_pb2"
|
||||
# @@protoc_insertion_point(class_scope:renderserver.UpdateSceneRequest)
|
||||
},
|
||||
)
|
||||
_sym_db.RegisterMessage(UpdateSceneRequest)
|
||||
|
||||
UpdateSceneResponse = _reflection.GeneratedProtocolMessageType(
|
||||
"UpdateSceneResponse",
|
||||
(_message.Message,),
|
||||
{
|
||||
"DESCRIPTOR": _UPDATESCENERESPONSE,
|
||||
"__module__": "renderserver_pb2"
|
||||
# @@protoc_insertion_point(class_scope:renderserver.UpdateSceneResponse)
|
||||
},
|
||||
)
|
||||
_sym_db.RegisterMessage(UpdateSceneResponse)
|
||||
|
||||
|
||||
_RENDERSERVER = _descriptor.ServiceDescriptor(
|
||||
name="RenderServer",
|
||||
full_name="renderserver.RenderServer",
|
||||
file=DESCRIPTOR,
|
||||
index=0,
|
||||
serialized_options=None,
|
||||
serialized_start=400,
|
||||
serialized_end=804,
|
||||
methods=[
|
||||
_descriptor.MethodDescriptor(
|
||||
name="AnimationStatus",
|
||||
full_name="renderserver.RenderServer.AnimationStatus",
|
||||
index=0,
|
||||
containing_service=None,
|
||||
input_type=_EMPTYREQUEST,
|
||||
output_type=_EMPTYRESPONSE,
|
||||
serialized_options=None,
|
||||
),
|
||||
_descriptor.MethodDescriptor(
|
||||
name="ManimStatus",
|
||||
full_name="renderserver.RenderServer.ManimStatus",
|
||||
index=1,
|
||||
containing_service=None,
|
||||
input_type=_MANIMSTATUSREQUEST,
|
||||
output_type=_MANIMSTATUSRESPONSE,
|
||||
serialized_options=None,
|
||||
),
|
||||
_descriptor.MethodDescriptor(
|
||||
name="UpdateScene",
|
||||
full_name="renderserver.RenderServer.UpdateScene",
|
||||
index=2,
|
||||
containing_service=None,
|
||||
input_type=_UPDATESCENEREQUEST,
|
||||
output_type=_UPDATESCENERESPONSE,
|
||||
serialized_options=None,
|
||||
),
|
||||
_descriptor.MethodDescriptor(
|
||||
name="NewScene",
|
||||
full_name="renderserver.RenderServer.NewScene",
|
||||
index=3,
|
||||
containing_service=None,
|
||||
input_type=_NEWSCENEREQUEST,
|
||||
output_type=_EMPTYRESPONSE,
|
||||
serialized_options=None,
|
||||
),
|
||||
_descriptor.MethodDescriptor(
|
||||
name="SceneFinished",
|
||||
full_name="renderserver.RenderServer.SceneFinished",
|
||||
index=4,
|
||||
containing_service=None,
|
||||
input_type=_EMPTYREQUEST,
|
||||
output_type=_EMPTYRESPONSE,
|
||||
serialized_options=None,
|
||||
),
|
||||
],
|
||||
)
|
||||
_sym_db.RegisterServiceDescriptor(_RENDERSERVER)
|
||||
|
||||
DESCRIPTOR.services_by_name["RenderServer"] = _RENDERSERVER
|
||||
|
||||
# @@protoc_insertion_point(module_scope)
|
||||
248
manim/grpc/gen/renderserver_pb2_grpc.py
Normal file
248
manim/grpc/gen/renderserver_pb2_grpc.py
Normal file
|
|
@ -0,0 +1,248 @@
|
|||
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
|
||||
import grpc
|
||||
|
||||
import renderserver_pb2 as renderserver__pb2
|
||||
|
||||
|
||||
class RenderServerStub(object):
|
||||
"""Missing associated documentation comment in .proto file"""
|
||||
|
||||
def __init__(self, channel):
|
||||
"""Constructor.
|
||||
|
||||
Args:
|
||||
channel: A grpc.Channel.
|
||||
"""
|
||||
self.AnimationStatus = channel.unary_unary(
|
||||
"/renderserver.RenderServer/AnimationStatus",
|
||||
request_serializer=renderserver__pb2.EmptyRequest.SerializeToString,
|
||||
response_deserializer=renderserver__pb2.EmptyResponse.FromString,
|
||||
)
|
||||
self.ManimStatus = channel.unary_unary(
|
||||
"/renderserver.RenderServer/ManimStatus",
|
||||
request_serializer=renderserver__pb2.ManimStatusRequest.SerializeToString,
|
||||
response_deserializer=renderserver__pb2.ManimStatusResponse.FromString,
|
||||
)
|
||||
self.UpdateScene = channel.unary_unary(
|
||||
"/renderserver.RenderServer/UpdateScene",
|
||||
request_serializer=renderserver__pb2.UpdateSceneRequest.SerializeToString,
|
||||
response_deserializer=renderserver__pb2.UpdateSceneResponse.FromString,
|
||||
)
|
||||
self.NewScene = channel.unary_unary(
|
||||
"/renderserver.RenderServer/NewScene",
|
||||
request_serializer=renderserver__pb2.NewSceneRequest.SerializeToString,
|
||||
response_deserializer=renderserver__pb2.EmptyResponse.FromString,
|
||||
)
|
||||
self.SceneFinished = channel.unary_unary(
|
||||
"/renderserver.RenderServer/SceneFinished",
|
||||
request_serializer=renderserver__pb2.EmptyRequest.SerializeToString,
|
||||
response_deserializer=renderserver__pb2.EmptyResponse.FromString,
|
||||
)
|
||||
|
||||
|
||||
class RenderServerServicer(object):
|
||||
"""Missing associated documentation comment in .proto file"""
|
||||
|
||||
def AnimationStatus(self, request, context):
|
||||
"""Used to signal that a new animation is ready to be animated."""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details("Method not implemented!")
|
||||
raise NotImplementedError("Method not implemented!")
|
||||
|
||||
def ManimStatus(self, request, context):
|
||||
"""Used to signal when manim starts and stops."""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details("Method not implemented!")
|
||||
raise NotImplementedError("Method not implemented!")
|
||||
|
||||
def UpdateScene(self, request, context):
|
||||
"""Missing associated documentation comment in .proto file"""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details("Method not implemented!")
|
||||
raise NotImplementedError("Method not implemented!")
|
||||
|
||||
def NewScene(self, request, context):
|
||||
"""Missing associated documentation comment in .proto file"""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details("Method not implemented!")
|
||||
raise NotImplementedError("Method not implemented!")
|
||||
|
||||
def SceneFinished(self, request, context):
|
||||
"""Missing associated documentation comment in .proto file"""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details("Method not implemented!")
|
||||
raise NotImplementedError("Method not implemented!")
|
||||
|
||||
|
||||
def add_RenderServerServicer_to_server(servicer, server):
|
||||
rpc_method_handlers = {
|
||||
"AnimationStatus": grpc.unary_unary_rpc_method_handler(
|
||||
servicer.AnimationStatus,
|
||||
request_deserializer=renderserver__pb2.EmptyRequest.FromString,
|
||||
response_serializer=renderserver__pb2.EmptyResponse.SerializeToString,
|
||||
),
|
||||
"ManimStatus": grpc.unary_unary_rpc_method_handler(
|
||||
servicer.ManimStatus,
|
||||
request_deserializer=renderserver__pb2.ManimStatusRequest.FromString,
|
||||
response_serializer=renderserver__pb2.ManimStatusResponse.SerializeToString,
|
||||
),
|
||||
"UpdateScene": grpc.unary_unary_rpc_method_handler(
|
||||
servicer.UpdateScene,
|
||||
request_deserializer=renderserver__pb2.UpdateSceneRequest.FromString,
|
||||
response_serializer=renderserver__pb2.UpdateSceneResponse.SerializeToString,
|
||||
),
|
||||
"NewScene": grpc.unary_unary_rpc_method_handler(
|
||||
servicer.NewScene,
|
||||
request_deserializer=renderserver__pb2.NewSceneRequest.FromString,
|
||||
response_serializer=renderserver__pb2.EmptyResponse.SerializeToString,
|
||||
),
|
||||
"SceneFinished": grpc.unary_unary_rpc_method_handler(
|
||||
servicer.SceneFinished,
|
||||
request_deserializer=renderserver__pb2.EmptyRequest.FromString,
|
||||
response_serializer=renderserver__pb2.EmptyResponse.SerializeToString,
|
||||
),
|
||||
}
|
||||
generic_handler = grpc.method_handlers_generic_handler(
|
||||
"renderserver.RenderServer", rpc_method_handlers
|
||||
)
|
||||
server.add_generic_rpc_handlers((generic_handler,))
|
||||
|
||||
|
||||
# This class is part of an EXPERIMENTAL API.
|
||||
class RenderServer(object):
|
||||
"""Missing associated documentation comment in .proto file"""
|
||||
|
||||
@staticmethod
|
||||
def AnimationStatus(
|
||||
request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None,
|
||||
):
|
||||
return grpc.experimental.unary_unary(
|
||||
request,
|
||||
target,
|
||||
"/renderserver.RenderServer/AnimationStatus",
|
||||
renderserver__pb2.EmptyRequest.SerializeToString,
|
||||
renderserver__pb2.EmptyResponse.FromString,
|
||||
options,
|
||||
channel_credentials,
|
||||
call_credentials,
|
||||
compression,
|
||||
wait_for_ready,
|
||||
timeout,
|
||||
metadata,
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def ManimStatus(
|
||||
request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None,
|
||||
):
|
||||
return grpc.experimental.unary_unary(
|
||||
request,
|
||||
target,
|
||||
"/renderserver.RenderServer/ManimStatus",
|
||||
renderserver__pb2.ManimStatusRequest.SerializeToString,
|
||||
renderserver__pb2.ManimStatusResponse.FromString,
|
||||
options,
|
||||
channel_credentials,
|
||||
call_credentials,
|
||||
compression,
|
||||
wait_for_ready,
|
||||
timeout,
|
||||
metadata,
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def UpdateScene(
|
||||
request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None,
|
||||
):
|
||||
return grpc.experimental.unary_unary(
|
||||
request,
|
||||
target,
|
||||
"/renderserver.RenderServer/UpdateScene",
|
||||
renderserver__pb2.UpdateSceneRequest.SerializeToString,
|
||||
renderserver__pb2.UpdateSceneResponse.FromString,
|
||||
options,
|
||||
channel_credentials,
|
||||
call_credentials,
|
||||
compression,
|
||||
wait_for_ready,
|
||||
timeout,
|
||||
metadata,
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def NewScene(
|
||||
request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None,
|
||||
):
|
||||
return grpc.experimental.unary_unary(
|
||||
request,
|
||||
target,
|
||||
"/renderserver.RenderServer/NewScene",
|
||||
renderserver__pb2.NewSceneRequest.SerializeToString,
|
||||
renderserver__pb2.EmptyResponse.FromString,
|
||||
options,
|
||||
channel_credentials,
|
||||
call_credentials,
|
||||
compression,
|
||||
wait_for_ready,
|
||||
timeout,
|
||||
metadata,
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def SceneFinished(
|
||||
request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None,
|
||||
):
|
||||
return grpc.experimental.unary_unary(
|
||||
request,
|
||||
target,
|
||||
"/renderserver.RenderServer/SceneFinished",
|
||||
renderserver__pb2.EmptyRequest.SerializeToString,
|
||||
renderserver__pb2.EmptyResponse.FromString,
|
||||
options,
|
||||
channel_credentials,
|
||||
call_credentials,
|
||||
compression,
|
||||
wait_for_ready,
|
||||
timeout,
|
||||
metadata,
|
||||
)
|
||||
0
manim/grpc/impl/__init__.py
Normal file
0
manim/grpc/impl/__init__.py
Normal file
262
manim/grpc/impl/frame_server_impl.py
Normal file
262
manim/grpc/impl/frame_server_impl.py
Normal file
|
|
@ -0,0 +1,262 @@
|
|||
from ...config import camera_config
|
||||
from ...config import file_writer_config
|
||||
from ...scene import scene
|
||||
from ..gen import frameserver_pb2
|
||||
from ..gen import frameserver_pb2_grpc
|
||||
from ..gen import renderserver_pb2
|
||||
from ..gen import renderserver_pb2_grpc
|
||||
from concurrent import futures
|
||||
from google.protobuf import json_format
|
||||
from watchdog.events import LoggingEventHandler, FileSystemEventHandler
|
||||
from watchdog.observers import Observer
|
||||
import grpc
|
||||
import subprocess as sp
|
||||
import threading
|
||||
import time
|
||||
import ctypes
|
||||
from ...utils.module_ops import (
|
||||
get_module,
|
||||
get_scene_classes_from_module,
|
||||
get_scenes_to_render,
|
||||
)
|
||||
from ...config.logger import logger
|
||||
from ...constants import JS_RENDERER_INFO
|
||||
|
||||
|
||||
class FrameServer(frameserver_pb2_grpc.FrameServerServicer):
|
||||
def animation_index_is_cached(self, animation_index):
|
||||
return animation_index < len(self.keyframes)
|
||||
|
||||
def __init__(self, server, scene_class):
|
||||
self.server = server
|
||||
self.keyframes = []
|
||||
self.scene = scene_class(self)
|
||||
self.scene_thread = threading.Thread(
|
||||
target=lambda s: s.render(), args=(self.scene,)
|
||||
)
|
||||
self.previous_frame_animation_index = None
|
||||
self.scene_finished = False
|
||||
|
||||
path = "./example_scenes/basic.py"
|
||||
event_handler = UpdateFrontendHandler(self)
|
||||
observer = Observer()
|
||||
observer.schedule(event_handler, path)
|
||||
observer.start()
|
||||
|
||||
# If a javascript renderer is running, notify it of the scene being served. If
|
||||
# not, spawn one and it will request the scene when it starts.
|
||||
with grpc.insecure_channel("localhost:50052") as channel:
|
||||
stub = renderserver_pb2_grpc.RenderServerStub(channel)
|
||||
request = renderserver_pb2.NewSceneRequest(name=str(self.scene))
|
||||
try:
|
||||
stub.NewScene(request)
|
||||
except grpc._channel._InactiveRpcError:
|
||||
logger.warning(f"No frontend was detected at localhost:50052.")
|
||||
try:
|
||||
sp.Popen(camera_config["js_renderer_path"])
|
||||
except PermissionError:
|
||||
logger.info(JS_RENDERER_INFO)
|
||||
self.server.stop(None)
|
||||
return
|
||||
|
||||
self.scene_thread.start()
|
||||
|
||||
def signal_pending_animation(self, animation_index):
|
||||
self.scene.start_animation = animation_index
|
||||
self.scene.animation_finished.set()
|
||||
return frameserver_pb2.FrameResponse(frame_pending=True)
|
||||
|
||||
def GetFrameAtTime(self, request, context):
|
||||
selected_scene = None
|
||||
if self.animation_index_is_cached(request.animation_index):
|
||||
selected_scene = self.keyframes[request.animation_index]
|
||||
else:
|
||||
return self.signal_pending_animation(request.animation_index)
|
||||
|
||||
# play() uses run_time and wait() uses duration TODO: Fix this inconsistency.
|
||||
# TODO: What about animations without a fixed duration?
|
||||
duration = (
|
||||
selected_scene.run_time
|
||||
if selected_scene.animations
|
||||
else selected_scene.duration
|
||||
)
|
||||
|
||||
if request.animation_offset > duration:
|
||||
if self.animation_index_is_cached(request.animation_index + 1):
|
||||
# TODO: Clone scenes to allow reuse.
|
||||
selected_scene = self.keyframes[request.animation_index + 1]
|
||||
else:
|
||||
return self.signal_pending_animation(request.animation_index + 1)
|
||||
|
||||
setattr(selected_scene, "camera", self.scene.camera)
|
||||
|
||||
if selected_scene.animations:
|
||||
# This is a call to play().
|
||||
selected_scene.update_animation_to_time(request.animation_offset)
|
||||
selected_scene.update_frame(
|
||||
selected_scene.moving_mobjects,
|
||||
selected_scene.static_image,
|
||||
)
|
||||
serialized_mobject_list, duration = selected_scene.add_frame(
|
||||
selected_scene.get_frame()
|
||||
)
|
||||
resp = list_to_frame_response(
|
||||
selected_scene, duration, serialized_mobject_list
|
||||
)
|
||||
return resp
|
||||
else:
|
||||
# This is a call to wait().
|
||||
if selected_scene.should_update_mobjects():
|
||||
# TODO, be smart about setting a static image
|
||||
# the same way Scene.play does
|
||||
selected_scene.update_animation_to_time(time)
|
||||
selected_scene.update_frame()
|
||||
serialized_mobject_list, duration = selected_scene.add_frame(
|
||||
selected_scene.get_frame()
|
||||
)
|
||||
frame_response = list_to_frame_response(
|
||||
selected_scene, duration, serialized_mobject_list
|
||||
)
|
||||
if (
|
||||
selected_scene.stop_condition is not None
|
||||
and selected_scene.stop_condition()
|
||||
):
|
||||
selected_scene.animation_finished.set()
|
||||
frame_response.frame_pending = True
|
||||
selected_scene.renderer_waiting = True
|
||||
return frame_response
|
||||
elif selected_scene.skip_animations:
|
||||
# Do nothing
|
||||
return
|
||||
else:
|
||||
selected_scene.update_frame()
|
||||
dt = 1 / selected_scene.camera.frame_rate
|
||||
serialized_mobject_list, duration = selected_scene.add_frame(
|
||||
selected_scene.get_frame(),
|
||||
num_frames=int(selected_scene.duration / dt),
|
||||
)
|
||||
resp = list_to_frame_response(
|
||||
selected_scene, duration, serialized_mobject_list
|
||||
)
|
||||
return resp
|
||||
|
||||
def RendererStatus(self, request, context):
|
||||
response = frameserver_pb2.RendererStatusResponse()
|
||||
response.scene_name = str(self.scene)
|
||||
return response
|
||||
|
||||
# def UpdateSceneLocation(self, request, context):
|
||||
# # Reload self.scene.
|
||||
# print(scene_classes_to_render)
|
||||
|
||||
# response = frameserver_pb2.SceneLocationResponse()
|
||||
# return response
|
||||
|
||||
|
||||
def list_to_frame_response(scene, duration, serialized_mobject_list):
|
||||
response = frameserver_pb2.FrameResponse()
|
||||
response.frame_pending = False
|
||||
response.duration = duration
|
||||
|
||||
for mob_serialization in serialized_mobject_list:
|
||||
mob_proto = response.mobjects.add()
|
||||
mob_proto.id = mob_serialization["id"]
|
||||
mob_proto.needs_redraw = mob_serialization["needs_redraw"]
|
||||
for point in mob_serialization["points"]:
|
||||
point_proto = mob_proto.points.add()
|
||||
point_proto.x = point[0]
|
||||
point_proto.y = point[1]
|
||||
point_proto.z = point[2]
|
||||
mob_proto.style.fill_color = mob_serialization["style"]["fill_color"]
|
||||
mob_proto.style.fill_opacity = float(mob_serialization["style"]["fill_opacity"])
|
||||
mob_proto.style.stroke_color = mob_serialization["style"]["stroke_color"]
|
||||
mob_proto.style.stroke_opacity = float(
|
||||
mob_serialization["style"]["stroke_opacity"]
|
||||
)
|
||||
mob_proto.style.stroke_width = float(mob_serialization["style"]["stroke_width"])
|
||||
return response
|
||||
|
||||
|
||||
class UpdateFrontendHandler(FileSystemEventHandler):
|
||||
"""Logs all the events captured."""
|
||||
|
||||
def __init__(self, frame_server):
|
||||
super().__init__()
|
||||
self.frame_server = frame_server
|
||||
|
||||
def on_moved(self, event):
|
||||
super().on_moved(event)
|
||||
raise NotImplementedError("Update not implemented for moved files.")
|
||||
|
||||
def on_deleted(self, event):
|
||||
super().on_deleted(event)
|
||||
raise NotImplementedError("Update not implemented for deleted files.")
|
||||
|
||||
def on_modified(self, event):
|
||||
super().on_modified(event)
|
||||
module = get_module(file_writer_config["input_file"])
|
||||
all_scene_classes = get_scene_classes_from_module(module)
|
||||
scene_classes_to_render = get_scenes_to_render(all_scene_classes)
|
||||
scene_class = scene_classes_to_render[0]
|
||||
|
||||
# Get the old thread's ID.
|
||||
old_thread_id = None
|
||||
old_thread = self.frame_server.scene_thread
|
||||
if hasattr(old_thread, "_thread_id"):
|
||||
old_thread_id = old_thread._thread_id
|
||||
if old_thread_id is None:
|
||||
for thread_id, thread in threading._active.items():
|
||||
if thread is old_thread:
|
||||
old_thread_id = thread_id
|
||||
|
||||
# Stop the old thread.
|
||||
res = ctypes.pythonapi.PyThreadState_SetAsyncExc(
|
||||
old_thread_id, ctypes.py_object(SystemExit)
|
||||
)
|
||||
if res > 1:
|
||||
ctypes.pythonapi.PyThreadState_SetAsyncExc(old_thread_id, 0)
|
||||
print("Exception raise failure")
|
||||
old_thread.join()
|
||||
|
||||
# Start a new thread.
|
||||
self.frame_server.initialize_scene(scene_class, start_animation=1)
|
||||
self.frame_server.scene.reached_start_animation.wait()
|
||||
|
||||
# Serialize data on Animations up to the target one.
|
||||
animations = []
|
||||
for scene in self.frame_server.keyframes:
|
||||
if scene.animations:
|
||||
animation_duration = scene.run_time
|
||||
if len(scene.animations) == 1:
|
||||
animation_name = str(scene.animations[0])
|
||||
else:
|
||||
animation_name = f"{str(scene.animations[0])}..."
|
||||
else:
|
||||
animation_duration = scene.duration
|
||||
animation_name = "Wait"
|
||||
animations.append(
|
||||
renderserver_pb2.Animation(
|
||||
name=animation_name,
|
||||
duration=animation_duration,
|
||||
)
|
||||
)
|
||||
|
||||
# Reset the renderer.
|
||||
with grpc.insecure_channel("localhost:50052") as channel:
|
||||
stub = renderserver_pb2_grpc.RenderServerStub(channel)
|
||||
request = renderserver_pb2.ManimStatusRequest(
|
||||
scene_name=str(self.frame_server.scene), animations=animations
|
||||
)
|
||||
try:
|
||||
stub.ManimStatus(request)
|
||||
except grpc._channel._InactiveRpcError:
|
||||
sp.Popen(camera_config["js_renderer_path"])
|
||||
|
||||
|
||||
def get(scene_class):
|
||||
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
|
||||
frameserver_pb2_grpc.add_FrameServerServicer_to_server(
|
||||
FrameServer(server, scene_class), server
|
||||
)
|
||||
server.add_insecure_port("localhost:50051")
|
||||
return server
|
||||
57
manim/grpc/proto/frameserver.proto
Normal file
57
manim/grpc/proto/frameserver.proto
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
syntax = "proto3";
|
||||
|
||||
package frameserver;
|
||||
|
||||
service FrameServer {
|
||||
// Updates the scene to the specified animation offset and returns a
|
||||
// serialization of the frame at that time.
|
||||
rpc GetFrameAtTime (FrameRequest) returns (FrameResponse);
|
||||
|
||||
// Used to signal to the renderer that manim is running.
|
||||
rpc RendererStatus (RendererStatusRequest) returns (RendererStatusResponse);
|
||||
|
||||
rpc UpdateSceneLocation (SceneLocationRequest) returns (SceneLocationResponse);
|
||||
}
|
||||
|
||||
message FrameRequest {
|
||||
int64 animation_index = 1;
|
||||
float animation_offset = 2;
|
||||
}
|
||||
|
||||
message Style {
|
||||
string fill_color = 1;
|
||||
float fill_opacity = 2;
|
||||
string stroke_color = 3;
|
||||
float stroke_opacity = 4;
|
||||
float stroke_width = 5;
|
||||
}
|
||||
|
||||
message Point {
|
||||
float x = 1;
|
||||
float y = 2;
|
||||
float z = 3;
|
||||
}
|
||||
|
||||
message MobjectData {
|
||||
int64 id = 1;
|
||||
repeated Point points = 2;
|
||||
Style style = 3;
|
||||
bool needs_redraw = 4;
|
||||
}
|
||||
|
||||
message FrameResponse {
|
||||
repeated MobjectData mobjects = 1;
|
||||
bool frame_pending = 2;
|
||||
bool animation_finished = 3;
|
||||
bool scene_finished = 4;
|
||||
float duration = 5;
|
||||
string animation_name = 6;
|
||||
}
|
||||
|
||||
message RendererStatusRequest {}
|
||||
message RendererStatusResponse {
|
||||
string scene_name = 1;
|
||||
}
|
||||
|
||||
message SceneLocationRequest {}
|
||||
message SceneLocationResponse {}
|
||||
51
manim/grpc/proto/renderserver.proto
Normal file
51
manim/grpc/proto/renderserver.proto
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
syntax = "proto3";
|
||||
|
||||
package renderserver;
|
||||
|
||||
service RenderServer {
|
||||
// Used to signal that a new animation is ready to be animated.
|
||||
rpc AnimationStatus (EmptyRequest) returns (EmptyResponse);
|
||||
|
||||
// Used to signal when manim starts and stops.
|
||||
rpc ManimStatus (ManimStatusRequest) returns (ManimStatusResponse);
|
||||
|
||||
rpc UpdateScene (UpdateSceneRequest) returns (UpdateSceneResponse);
|
||||
|
||||
rpc NewScene (NewSceneRequest) returns (EmptyResponse);
|
||||
|
||||
rpc SceneFinished (EmptyRequest) returns (EmptyResponse);
|
||||
}
|
||||
|
||||
message EmptyRequest {}
|
||||
message EmptyResponse {}
|
||||
|
||||
message NewSceneRequest {
|
||||
string name = 1;
|
||||
}
|
||||
|
||||
message NewSceneResponse {}
|
||||
|
||||
message Animation {
|
||||
string name = 1;
|
||||
float duration = 2;
|
||||
}
|
||||
|
||||
message AnimationStatusRequest {}
|
||||
message AnimationStatusResponse {}
|
||||
|
||||
message ManimStatusRequest {
|
||||
// The name of the scene whose frames are currently being served. This is
|
||||
// only seen if a javascript renderer is running prior to manim being
|
||||
// started.
|
||||
string scene_name = 1;
|
||||
|
||||
// Indicates that the current Scene is finished.
|
||||
bool scene_finished = 2;
|
||||
|
||||
// Indicates that the Animations have been updated and should be changed.
|
||||
repeated Animation animations = 3;
|
||||
}
|
||||
message ManimStatusResponse {}
|
||||
|
||||
message UpdateSceneRequest {}
|
||||
message UpdateSceneResponse {}
|
||||
9
manim/grpc/update_protos.sh
Executable file
9
manim/grpc/update_protos.sh
Executable file
|
|
@ -0,0 +1,9 @@
|
|||
#!/bin/sh
|
||||
|
||||
python \
|
||||
-m grpc_tools.protoc \
|
||||
-I./proto \
|
||||
--python_out=./gen \
|
||||
--grpc_python_out=./gen \
|
||||
./proto/frameserver.proto \
|
||||
./proto/renderserver.proto
|
||||
|
|
@ -52,6 +52,7 @@ class Mobject(Container):
|
|||
|
||||
def __init__(self, **kwargs):
|
||||
Container.__init__(self, **kwargs)
|
||||
self.point_hash = None
|
||||
self.submobjects = []
|
||||
self.color = Color(self.color)
|
||||
if self.name is None:
|
||||
|
|
|
|||
|
|
@ -13,8 +13,7 @@ __all__ = [
|
|||
|
||||
import itertools as it
|
||||
import sys
|
||||
|
||||
from colour import Color
|
||||
import colour
|
||||
|
||||
from ...constants import *
|
||||
from ...mobject.mobject import Mobject
|
||||
|
|
@ -211,21 +210,29 @@ class VMobject(Mobject):
|
|||
self.color_using_background_image(background_image_file)
|
||||
return self
|
||||
|
||||
def get_style(self):
|
||||
return {
|
||||
"fill_color": self.get_fill_colors(),
|
||||
"fill_opacity": self.get_fill_opacities(),
|
||||
"stroke_color": self.get_stroke_colors(),
|
||||
"stroke_width": self.get_stroke_width(),
|
||||
def get_style(self, simple=False):
|
||||
ret = {
|
||||
"stroke_opacity": self.get_stroke_opacity(),
|
||||
"background_stroke_color": self.get_stroke_colors(background=True),
|
||||
"background_stroke_width": self.get_stroke_width(background=True),
|
||||
"background_stroke_opacity": self.get_stroke_opacity(background=True),
|
||||
"sheen_factor": self.get_sheen_factor(),
|
||||
"sheen_direction": self.get_sheen_direction(),
|
||||
"background_image_file": self.get_background_image_file(),
|
||||
"stroke_width": self.get_stroke_width(),
|
||||
}
|
||||
|
||||
if simple:
|
||||
ret["fill_color"] = colour.rgb2hex(self.get_fill_color().get_rgb())
|
||||
ret["fill_opacity"] = self.get_fill_opacity()
|
||||
ret["stroke_color"] = colour.rgb2hex(self.get_stroke_color().get_rgb())
|
||||
else:
|
||||
ret["fill_color"] = self.get_fill_colors()
|
||||
ret["fill_opacity"] = self.get_fill_opacities()
|
||||
ret["stroke_color"] = self.get_stroke_colors()
|
||||
ret["background_stroke_color"] = self.get_stroke_colors(background=True)
|
||||
ret["background_stroke_width"] = self.get_stroke_width(background=True)
|
||||
ret["background_stroke_opacity"] = self.get_stroke_opacity(background=True)
|
||||
ret["sheen_factor"] = self.get_sheen_factor()
|
||||
ret["sheen_direction"] = self.get_sheen_direction()
|
||||
ret["background_image_file"] = self.get_background_image_file()
|
||||
|
||||
return ret
|
||||
|
||||
def match_style(self, vmobject, family=True):
|
||||
self.set_style(**vmobject.get_style(), family=False)
|
||||
|
||||
|
|
@ -290,7 +297,7 @@ class VMobject(Mobject):
|
|||
return self.get_fill_opacities()[0]
|
||||
|
||||
def get_fill_colors(self):
|
||||
return [Color(rgb=rgba[:3]) for rgba in self.get_fill_rgbas()]
|
||||
return [colour.Color(rgb=rgba[:3]) for rgba in self.get_fill_rgbas()]
|
||||
|
||||
def get_fill_opacities(self):
|
||||
return self.get_fill_rgbas()[:, 3]
|
||||
|
|
@ -319,7 +326,9 @@ class VMobject(Mobject):
|
|||
return self.get_stroke_opacities(background)[0]
|
||||
|
||||
def get_stroke_colors(self, background=False):
|
||||
return [Color(rgb=rgba[:3]) for rgba in self.get_stroke_rgbas(background)]
|
||||
return [
|
||||
colour.Color(rgb=rgba[:3]) for rgba in self.get_stroke_rgbas(background)
|
||||
]
|
||||
|
||||
def get_stroke_opacities(self, background=False):
|
||||
return self.get_stroke_rgbas(background)[:, 3]
|
||||
|
|
|
|||
145
manim/scene/js_scene.py
Normal file
145
manim/scene/js_scene.py
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
from . import scene
|
||||
from ..camera.camera import Camera
|
||||
from ..camera.js_camera import JsCamera
|
||||
from ..config import config
|
||||
from ..grpc.gen import renderserver_pb2
|
||||
from ..grpc.gen import renderserver_pb2_grpc
|
||||
from ..grpc.impl.frame_server_impl import FrameServer
|
||||
from ..mobject.mobject import Mobject
|
||||
from ..constants import DEFAULT_WAIT_TIME
|
||||
from threading import Event
|
||||
import copy
|
||||
import grpc
|
||||
import inspect
|
||||
import random
|
||||
import string
|
||||
import types
|
||||
from ..config.logger import logger
|
||||
|
||||
|
||||
def get_random_name(name_map):
|
||||
while True:
|
||||
random_name = "".join(random.sample(string.ascii_lowercase, k=10))
|
||||
if random_name not in name_map:
|
||||
return random_name
|
||||
|
||||
|
||||
class JsScene(scene.Scene):
|
||||
def __init__(self, frame_server):
|
||||
super().__init__(camera_class=JsCamera)
|
||||
self.frame_server = frame_server
|
||||
self.start_animation = 0
|
||||
self.reached_start_animation = Event()
|
||||
self.animation_finished = Event()
|
||||
self.renderer_waiting = False
|
||||
|
||||
def __deepcopy__(self, memo):
|
||||
cls = self.__class__
|
||||
result = cls.__new__(cls)
|
||||
memo[id(self)] = result
|
||||
for k, v in self.__dict__.items():
|
||||
if type(v) in [FrameServer, Event, Camera]:
|
||||
continue
|
||||
setattr(result, k, copy.deepcopy(v, memo))
|
||||
|
||||
# Update updaters
|
||||
for mobject in self.mobjects:
|
||||
cloned_updaters = []
|
||||
for updater in mobject.updaters:
|
||||
# Make the cloned updater use the cloned Mobjects as free variables
|
||||
# rather than the original ones.
|
||||
# TODO: The the same for function calls recursively.
|
||||
free_variable_map = inspect.getclosurevars(updater).nonlocals
|
||||
cloned_co_freevars = []
|
||||
cloned_closure = []
|
||||
for i, free_variable_name in enumerate(updater.__code__.co_freevars):
|
||||
free_variable_value = free_variable_map[free_variable_name]
|
||||
if isinstance(free_variable_value, Mobject):
|
||||
random_name = get_random_name(free_variable_map)
|
||||
|
||||
# Put the cloned Mobject in the function's scope.
|
||||
free_variable_map[random_name] = memo[id(free_variable_value)]
|
||||
|
||||
# Add the cloned Mobject's name to the free variable list.
|
||||
cloned_co_freevars.append(random_name)
|
||||
|
||||
# Add a cell containing the cloned Mobject's reference to the
|
||||
# closure list.
|
||||
cloned_closure.append(
|
||||
types.CellType(memo[id(free_variable_value)])
|
||||
)
|
||||
else:
|
||||
cloned_co_freevars.append(free_variable_name)
|
||||
cloned_closure.append(updater.__closure__[i])
|
||||
|
||||
cloned_updater = types.FunctionType(
|
||||
updater.__code__.replace(co_freevars=tuple(cloned_co_freevars)),
|
||||
updater.__globals__,
|
||||
updater.__name__,
|
||||
updater.__defaults__,
|
||||
tuple(cloned_closure),
|
||||
)
|
||||
cloned_updaters.append(cloned_updater)
|
||||
memo[id(mobject)].updaters = cloned_updaters
|
||||
return result
|
||||
|
||||
def render(self):
|
||||
try:
|
||||
self.construct()
|
||||
except scene.EndSceneEarlyException:
|
||||
pass
|
||||
|
||||
self.frame_server.scene_finished = True
|
||||
with grpc.insecure_channel("localhost:50052") as channel:
|
||||
stub = renderserver_pb2_grpc.RenderServerStub(channel)
|
||||
try:
|
||||
stub.SceneFinished(renderserver_pb2.EmptyRequest())
|
||||
except grpc._channel._InactiveRpcError as e:
|
||||
logger.error(e)
|
||||
|
||||
def progress_through_animations(self):
|
||||
self.frame_server.keyframes.append(copy.deepcopy(self))
|
||||
self.animation_finished.clear()
|
||||
if self.num_plays == self.start_animation:
|
||||
with grpc.insecure_channel("localhost:50052") as channel:
|
||||
stub = renderserver_pb2_grpc.RenderServerStub(channel)
|
||||
try:
|
||||
stub.AnimationStatus(renderserver_pb2.EmptyRequest())
|
||||
except grpc._channel._InactiveRpcError as e:
|
||||
logger.error(e)
|
||||
self.animation_finished.wait()
|
||||
|
||||
@scene.handle_play_like_call
|
||||
def wait(self, duration=DEFAULT_WAIT_TIME, stop_condition=None):
|
||||
self.update_mobjects(dt=0) # Any problems with this?
|
||||
self.animations = []
|
||||
self.duration = duration
|
||||
self.stop_condition = stop_condition
|
||||
self.last_t = 0
|
||||
|
||||
self.frame_server.keyframes.append(copy.deepcopy(self))
|
||||
self.animation_finished.clear()
|
||||
if self.num_plays == self.start_animation:
|
||||
with grpc.insecure_channel("localhost:50052") as channel:
|
||||
stub = renderserver_pb2_grpc.RenderServerStub(channel)
|
||||
try:
|
||||
stub.AnimationStatus(renderserver_pb2.EmptyRequest())
|
||||
except grpc._channel._InactiveRpcError as e:
|
||||
logger.error(e)
|
||||
self.animation_finished.wait()
|
||||
|
||||
def add_frame(self, serialized_frame, num_frames=1):
|
||||
dt = 1 / self.camera.frame_rate
|
||||
self.increment_time(num_frames * dt)
|
||||
if num_frames != 1:
|
||||
duration = num_frames / self.camera.frame_rate
|
||||
else:
|
||||
duration = 0
|
||||
return self.camera.serialized_frame, duration
|
||||
|
||||
def get_frame(self):
|
||||
return self.camera.serialized_frame
|
||||
|
||||
|
||||
if config["use_js_renderer"]:
|
||||
scene.Scene = JsScene
|
||||
|
|
@ -25,6 +25,39 @@ from ..utils.iterables import list_update
|
|||
from ..utils.hashing import get_hash_from_play_call, get_hash_from_wait_call
|
||||
|
||||
|
||||
def handle_play_like_call(func):
|
||||
"""
|
||||
This method is used internally to wrap the
|
||||
passed function, into a function that
|
||||
actually writes to the video stream.
|
||||
Simultaneously, it also adds to the number
|
||||
of animations played.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
func : function
|
||||
The play() like function that has to be
|
||||
written to the video file stream.
|
||||
|
||||
Returns
|
||||
-------
|
||||
function
|
||||
The play() like function that can now write
|
||||
to the video file stream.
|
||||
"""
|
||||
|
||||
def wrapper(self, *args, **kwargs):
|
||||
allow_write = not file_writer_config["skip_animations"]
|
||||
if not self.camera.use_js_renderer:
|
||||
self.file_writer.begin_animation(allow_write)
|
||||
func(self, *args, **kwargs)
|
||||
if not self.camera.use_js_renderer:
|
||||
self.file_writer.end_animation(allow_write)
|
||||
self.num_plays += 1
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
class Scene(Container):
|
||||
"""A Scene is the canvas of your animation.
|
||||
|
||||
|
|
@ -65,11 +98,13 @@ class Scene(Container):
|
|||
def __init__(self, **kwargs):
|
||||
Container.__init__(self, **kwargs)
|
||||
self.camera = self.camera_class(**camera_config)
|
||||
self.file_writer = SceneFileWriter(
|
||||
self,
|
||||
**file_writer_config,
|
||||
)
|
||||
if not self.camera.use_js_renderer:
|
||||
self.file_writer = SceneFileWriter(
|
||||
self,
|
||||
**file_writer_config,
|
||||
)
|
||||
self.play_hashes_list = []
|
||||
|
||||
self.mobjects = []
|
||||
self.original_skipping_status = file_writer_config["skip_animations"]
|
||||
# TODO, remove need for foreground mobjects
|
||||
|
|
@ -82,10 +117,16 @@ class Scene(Container):
|
|||
np.random.seed(self.random_seed)
|
||||
|
||||
self.setup()
|
||||
|
||||
def render(self):
|
||||
"""
|
||||
Render this Scene.
|
||||
"""
|
||||
try:
|
||||
self.construct()
|
||||
except EndSceneEarlyException:
|
||||
pass
|
||||
|
||||
self.tear_down()
|
||||
# We have to reset these settings in case of multiple renders.
|
||||
file_writer_config["skip_animations"] = False
|
||||
|
|
@ -204,7 +245,7 @@ class Scene(Container):
|
|||
self.foreground_mobjects,
|
||||
)
|
||||
if background is not None:
|
||||
self.camera.set_pixel_array(background)
|
||||
self.camera.set_frame_to_background(background)
|
||||
else:
|
||||
self.camera.reset()
|
||||
|
||||
|
|
@ -684,8 +725,7 @@ class Scene(Container):
|
|||
ProgressDisplay
|
||||
The CommandLine Progress Bar.
|
||||
"""
|
||||
run_time = self.get_run_time(animations)
|
||||
time_progression = self.get_time_progression(run_time)
|
||||
time_progression = self.get_time_progression(self.run_time)
|
||||
time_progression.set_description(
|
||||
"".join(
|
||||
[
|
||||
|
|
@ -868,36 +908,6 @@ class Scene(Container):
|
|||
|
||||
return wrapper
|
||||
|
||||
def handle_play_like_call(func):
|
||||
"""
|
||||
This method is used internally to wrap the
|
||||
passed function, into a function that
|
||||
actually writes to the video stream.
|
||||
Simultaneously, it also adds to the number
|
||||
of animations played.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
func : function
|
||||
The play() like function that has to be
|
||||
written to the video file stream.
|
||||
|
||||
Returns
|
||||
-------
|
||||
function
|
||||
The play() like function that can now write
|
||||
to the video file stream.
|
||||
"""
|
||||
|
||||
def wrapper(self, *args, **kwargs):
|
||||
allow_write = not file_writer_config["skip_animations"]
|
||||
self.file_writer.begin_animation(allow_write)
|
||||
func(self, *args, **kwargs)
|
||||
self.file_writer.end_animation(allow_write)
|
||||
self.num_plays += 1
|
||||
|
||||
return wrapper
|
||||
|
||||
def begin_animations(self, animations):
|
||||
"""
|
||||
This method begins the list of animations that is passed,
|
||||
|
|
@ -914,32 +924,33 @@ class Scene(Container):
|
|||
# Begin animation
|
||||
animation.begin()
|
||||
|
||||
def progress_through_animations(self, animations):
|
||||
def progress_through_animations(self):
|
||||
"""
|
||||
This method progresses through each animation
|
||||
in the list passed and and updates the frames as required.
|
||||
"""
|
||||
for t in self.get_animation_time_progression(self.animations):
|
||||
self.update_animation_to_time(t)
|
||||
self.update_frame(self.moving_mobjects, self.static_image)
|
||||
self.add_frame(self.get_frame())
|
||||
|
||||
def update_animation_to_time(self, t):
|
||||
"""
|
||||
Updates the current animation to the specified time.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
animations : list
|
||||
List of involved animations.
|
||||
t : int
|
||||
Offset from the start of the animation to which to update the current
|
||||
animation.
|
||||
"""
|
||||
# Paint all non-moving objects onto the screen, so they don't
|
||||
# have to be rendered every frame
|
||||
moving_mobjects = self.get_moving_mobjects(*animations)
|
||||
self.update_frame(excluded_mobjects=moving_mobjects)
|
||||
static_image = self.get_frame()
|
||||
last_t = 0
|
||||
for t in self.get_animation_time_progression(animations):
|
||||
dt = t - last_t
|
||||
last_t = t
|
||||
for animation in animations:
|
||||
animation.update_mobjects(dt)
|
||||
alpha = t / animation.run_time
|
||||
animation.interpolate(alpha)
|
||||
self.update_mobjects(dt)
|
||||
self.update_frame(moving_mobjects, static_image)
|
||||
self.add_frames(self.get_frame())
|
||||
dt = t - self.last_t
|
||||
self.last_t = t
|
||||
for animation in self.animations:
|
||||
animation.update_mobjects(dt)
|
||||
alpha = t / animation.run_time
|
||||
animation.interpolate(alpha)
|
||||
self.update_mobjects(dt)
|
||||
|
||||
def finish_animations(self, animations):
|
||||
"""
|
||||
|
|
@ -977,10 +988,20 @@ class Scene(Container):
|
|||
if len(args) == 0:
|
||||
warnings.warn("Called Scene.play with no animations")
|
||||
return
|
||||
animations = self.compile_play_args_to_animation_list(*args, **kwargs)
|
||||
self.begin_animations(animations)
|
||||
self.progress_through_animations(animations)
|
||||
self.finish_animations(animations)
|
||||
self.animations = self.compile_play_args_to_animation_list(*args, **kwargs)
|
||||
self.begin_animations(self.animations)
|
||||
|
||||
# Paint all non-moving objects onto the screen, so they don't
|
||||
# have to be rendered every frame
|
||||
self.moving_mobjects = self.get_moving_mobjects(*self.animations)
|
||||
self.update_frame(excluded_mobjects=self.moving_mobjects)
|
||||
self.static_image = self.get_frame()
|
||||
self.last_t = 0
|
||||
self.run_time = self.get_run_time(self.animations)
|
||||
|
||||
self.progress_through_animations()
|
||||
|
||||
self.finish_animations(self.animations)
|
||||
|
||||
def clean_up_animations(self, *animations):
|
||||
"""
|
||||
|
|
@ -1073,29 +1094,29 @@ class Scene(Container):
|
|||
The scene, after waiting.
|
||||
"""
|
||||
self.update_mobjects(dt=0) # Any problems with this?
|
||||
self.animations = []
|
||||
self.duration = duration
|
||||
self.stop_condition = stop_condition
|
||||
self.last_t = 0
|
||||
|
||||
if self.should_update_mobjects():
|
||||
time_progression = self.get_wait_time_progression(duration, stop_condition)
|
||||
# TODO, be smart about setting a static image
|
||||
# the same way Scene.play does
|
||||
last_t = 0
|
||||
for t in time_progression:
|
||||
dt = t - last_t
|
||||
last_t = t
|
||||
self.update_mobjects(dt)
|
||||
self.update_animation_to_time(t)
|
||||
self.update_frame()
|
||||
self.add_frames(self.get_frame())
|
||||
self.add_frame(self.get_frame())
|
||||
if stop_condition is not None and stop_condition():
|
||||
time_progression.close()
|
||||
break
|
||||
elif file_writer_config["skip_animations"]:
|
||||
elif self.skip_animations:
|
||||
# Do nothing
|
||||
return self
|
||||
else:
|
||||
self.update_frame()
|
||||
dt = 1 / self.camera.frame_rate
|
||||
n_frames = int(duration / dt)
|
||||
frame = self.get_frame()
|
||||
self.add_frames(*[frame] * n_frames)
|
||||
self.add_frame(self.get_frame(), num_frames=int(duration / dt))
|
||||
return self
|
||||
|
||||
def wait_until(self, stop_condition, max_time=60):
|
||||
|
|
@ -1145,20 +1166,22 @@ class Scene(Container):
|
|||
file_writer_config["skip_animations"] = self.original_skipping_status
|
||||
return self
|
||||
|
||||
def add_frames(self, *frames):
|
||||
def add_frame(self, frame, num_frames=1):
|
||||
"""
|
||||
Adds a frame to the video_file_stream
|
||||
|
||||
Parameters
|
||||
----------
|
||||
*frames : numpy.ndarray
|
||||
The frames to add, as pixel arrays.
|
||||
frame : numpy.ndarray
|
||||
The frame to add, as a pixel array.
|
||||
num_frames: int
|
||||
The number of times to add frame.
|
||||
"""
|
||||
dt = 1 / self.camera.frame_rate
|
||||
self.increment_time(len(frames) * dt)
|
||||
self.increment_time(num_frames * dt)
|
||||
if file_writer_config["skip_animations"]:
|
||||
return
|
||||
for frame in frames:
|
||||
for _ in range(num_frames):
|
||||
self.file_writer.write_frame(frame)
|
||||
|
||||
def add_sound(self, sound_file, time_offset=0, gain=None, **kwargs):
|
||||
|
|
|
|||
|
|
@ -366,7 +366,7 @@ class SceneFileWriter(object):
|
|||
self.update_frame()
|
||||
n_frames = 1
|
||||
frame = self.get_frame()
|
||||
self.add_frames(*[frame] * n_frames)
|
||||
self.add_frame(*[frame] * n_frames)
|
||||
b = datetime.datetime.now()
|
||||
time_diff = (b - a).total_seconds()
|
||||
frame_duration = 1 / self.scene.camera.frame_rate
|
||||
|
|
|
|||
|
|
@ -10,10 +10,11 @@ __all__ = [
|
|||
|
||||
|
||||
import os
|
||||
import subprocess as sp
|
||||
import platform
|
||||
import numpy as np
|
||||
import time
|
||||
import re
|
||||
import subprocess as sp
|
||||
|
||||
|
||||
def add_extension_if_not_present(file_name, extension):
|
||||
|
|
|
|||
105
manim/utils/module_ops.py
Normal file
105
manim/utils/module_ops.py
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
from .. import constants
|
||||
from ..config import file_writer_config
|
||||
from ..config.logger import logger, console
|
||||
import importlib.util
|
||||
import inspect
|
||||
import os
|
||||
import sys
|
||||
import types
|
||||
|
||||
|
||||
def get_module(file_name):
|
||||
if file_name == "-":
|
||||
module = types.ModuleType("input_scenes")
|
||||
logger.info(
|
||||
"Enter the animation's code & end with an EOF (CTRL+D on Linux/Unix, CTRL+Z on Windows):"
|
||||
)
|
||||
code = sys.stdin.read()
|
||||
if not code.startswith("from manim import"):
|
||||
logger.warn(
|
||||
"Didn't find an import statement for Manim. Importing automatically..."
|
||||
)
|
||||
code = "from manim import *\n" + code
|
||||
logger.info("Rendering animation from typed code...")
|
||||
try:
|
||||
exec(code, module.__dict__)
|
||||
return module
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to render scene: {str(e)}")
|
||||
sys.exit(2)
|
||||
else:
|
||||
if os.path.exists(file_name):
|
||||
if file_name[-3:] != ".py":
|
||||
raise Exception(f"{file_name} is not a valid Manim python script.")
|
||||
module_name = file_name[:-3].replace(os.sep, ".").split(".")[-1]
|
||||
spec = importlib.util.spec_from_file_location(module_name, file_name)
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
sys.modules[module_name] = module
|
||||
spec.loader.exec_module(module)
|
||||
return module
|
||||
else:
|
||||
raise FileNotFoundError(f"{file_name} not found")
|
||||
|
||||
|
||||
def get_scene_classes_from_module(module):
|
||||
from ..scene.scene import Scene
|
||||
|
||||
def is_child_scene(obj, module):
|
||||
return (
|
||||
inspect.isclass(obj)
|
||||
and issubclass(obj, Scene)
|
||||
and obj != Scene
|
||||
and obj.__module__.startswith(module.__name__)
|
||||
)
|
||||
|
||||
return [
|
||||
member[1]
|
||||
for member in inspect.getmembers(module, lambda x: is_child_scene(x, module))
|
||||
]
|
||||
|
||||
|
||||
def get_scenes_to_render(scene_classes):
|
||||
if not scene_classes:
|
||||
logger.error(constants.NO_SCENE_MESSAGE)
|
||||
return []
|
||||
if file_writer_config["write_all"]:
|
||||
return scene_classes
|
||||
result = []
|
||||
for scene_name in file_writer_config["scene_names"]:
|
||||
found = False
|
||||
for scene_class in scene_classes:
|
||||
if scene_class.__name__ == scene_name:
|
||||
result.append(scene_class)
|
||||
found = True
|
||||
break
|
||||
if not found and (scene_name != ""):
|
||||
logger.error(constants.SCENE_NOT_FOUND_MESSAGE.format(scene_name))
|
||||
if result:
|
||||
return result
|
||||
return (
|
||||
[scene_classes[0]]
|
||||
if len(scene_classes) == 1
|
||||
else prompt_user_for_choice(scene_classes)
|
||||
)
|
||||
|
||||
|
||||
def prompt_user_for_choice(scene_classes):
|
||||
num_to_class = {}
|
||||
for count, scene_class in enumerate(scene_classes):
|
||||
count += 1 # start with 1 instead of 0
|
||||
name = scene_class.__name__
|
||||
console.print(f"{count}: {name}", style="logging.level.info")
|
||||
num_to_class[count] = scene_class
|
||||
try:
|
||||
user_input = console.input(
|
||||
f"[log.message] {constants.CHOOSE_NUMBER_MESSAGE} [/log.message]"
|
||||
)
|
||||
return [
|
||||
num_to_class[int(num_str)]
|
||||
for num_str in re.split(r"\s*,\s*", user_input.strip())
|
||||
]
|
||||
except KeyError:
|
||||
logger.error(constants.INVALID_NUMBER_MESSAGE)
|
||||
sys.exit(2)
|
||||
except EOFError:
|
||||
sys.exit(1)
|
||||
862
poetry.lock
generated
862
poetry.lock
generated
File diff suppressed because it is too large
Load diff
|
|
@ -39,10 +39,15 @@ pycairo = [
|
|||
{ version = "^1.19", markers = "sys_platform == 'win32'", source="testpypi" },
|
||||
]
|
||||
dataclasses = {version = "^0.7", python = "~3.6"}
|
||||
grpcio = "*"
|
||||
grpcio-tools = "*"
|
||||
watchdog = "*"
|
||||
|
||||
[tool.poetry.dev-dependencies]
|
||||
pytest = "^6.0"
|
||||
pylint = "*"
|
||||
guzzle_sphinx_theme = "*"
|
||||
recommonmark = "*"
|
||||
|
||||
[tool.poetry.dev-dependencies.black]
|
||||
version = "^20.8b1"
|
||||
|
|
|
|||
|
|
@ -8,6 +8,9 @@ pydub
|
|||
pygments
|
||||
pyreadline; sys_platform == 'win32'
|
||||
rich>=4.2.1
|
||||
grpcio
|
||||
grpcio-tools
|
||||
watchdog
|
||||
|
||||
# for development only:
|
||||
# pytest
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ class GraphicalUnitTester:
|
|||
|
||||
# By invoking this, the scene is rendered.
|
||||
self.scene = scene_object()
|
||||
self.scene.render()
|
||||
|
||||
def _load_data(self):
|
||||
"""Load the np.array of the last frame of a pre-rendered scene. If not found, throw FileNotFoundError.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue