sreepathi-ravikumar commited on
Commit
987fe9c
·
verified ·
1 Parent(s): c92c393

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +118 -27
app.py CHANGED
@@ -21,8 +21,49 @@ os.makedirs(TEMP_DIR, exist_ok=True)
21
  # API Key for security (optional)
22
  API_KEY = "rkmentormindzofficaltokenkey12345"
23
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  def create_manim_script(problem_data, script_path):
25
- """Generate Manim script from problem data"""
 
 
26
  settings = problem_data.get("video_settings", {
27
  "background_color": "#0f0f23",
28
  "text_color": "WHITE",
@@ -30,21 +71,25 @@ def create_manim_script(problem_data, script_path):
30
  "font": "CMU Serif",
31
  "text_size": 36,
32
  "equation_size": 42,
33
- "title_size": 48
 
34
  })
35
-
36
  slides = problem_data.get("slides", [])
37
  if not slides:
38
  raise ValueError("No slides provided in input data")
39
-
40
  slides_repr = repr(slides)
41
-
 
 
 
42
  manim_code = f'''
43
  from manim import *
44
  import textwrap
45
-
46
  class GeneratedMathScene(Scene):
47
  def construct(self):
 
48
  self.camera.background_color = "{settings.get('background_color', '#0f0f23')}"
49
  default_color = {settings.get('text_color', 'WHITE')}
50
  highlight_color = {settings.get('highlight_color', 'YELLOW')}
@@ -52,14 +97,38 @@ class GeneratedMathScene(Scene):
52
  text_size = {settings.get('text_size', 36)}
53
  equation_size = {settings.get('equation_size', 42)}
54
  title_size = {settings.get('title_size', 48)}
 
55
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  content_group = VGroup()
57
  current_y = 3.0
58
  line_spacing = 0.8
59
- screen_bottom = -3.5
60
-
61
  slides = {slides_repr}
62
 
 
63
  for idx, slide in enumerate(slides):
64
  obj = None
65
  content = slide.get("content", "")
@@ -68,9 +137,20 @@ class GeneratedMathScene(Scene):
68
  slide_type = slide.get("type", "text")
69
 
70
  if slide_type == "title":
71
- obj = Text(content, color=highlight_color, font=default_font, font_size=title_size)
72
- if obj.width > 12:
73
- obj.set_width(12)
 
 
 
 
 
 
 
 
 
 
 
74
  obj.move_to(ORIGIN)
75
  self.play(FadeIn(obj), run_time=duration * 0.8)
76
  self.wait(duration * 0.3)
@@ -78,27 +158,37 @@ class GeneratedMathScene(Scene):
78
  continue
79
 
80
  elif slide_type == "text":
81
- # Wrap long text to multiple lines automatically
82
- if len(content) > 50:
83
- lines = textwrap.wrap(content, width=50)
84
- wrapped_content = "\
85
- ".join(lines)
86
- obj = Text(wrapped_content, color=default_color, font=default_font, font_size=text_size, line_spacing=1)
87
- else:
88
- obj = Text(content, color=default_color, font=default_font, font_size=text_size)
89
 
90
  elif slide_type == "equation":
91
- obj = MathTex(content, color=default_color, font_size=equation_size)
92
- if obj.width > 12:
93
- obj.scale(12 / obj.width)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
 
95
  if obj:
 
96
  obj.to_edge(LEFT, buff=0.3)
97
  obj.shift(UP * (current_y - obj.height/2))
98
 
99
  obj_bottom = obj.get_bottom()[1]
100
- if obj_bottom < screen_bottom:
101
- scroll_amount = abs(obj_bottom - screen_bottom) + 0.3
102
  self.play(content_group.animate.shift(UP * scroll_amount), run_time=0.5)
103
  current_y += scroll_amount
104
  obj.shift(UP * scroll_amount)
@@ -114,15 +204,16 @@ class GeneratedMathScene(Scene):
114
  self.play(Write(obj), run_time=duration)
115
 
116
  content_group.add(obj)
117
- current_y -= (obj.height + line_spacing)
 
118
  self.wait(0.3)
119
 
120
  if len(content_group) > 0:
121
  final_box = SurroundingRectangle(content_group[-1], color=highlight_color, buff=0.2)
122
  self.play(Create(final_box), run_time=0.8)
123
  self.wait(1.5)
124
- '''
125
-
126
  with open(script_path, 'w', encoding='utf-8') as f:
127
  f.write(manim_code)
128
 
 
21
  # API Key for security (optional)
22
  API_KEY = "rkmentormindzofficaltokenkey12345"
23
 
24
+ import textwrap
25
+ from manim import *
26
+
27
+ def make_wrapped_paragraph(content, max_width, color, font, font_size, line_spacing, align_left=True):
28
+ """
29
+ Build a vertically stacked group of Text lines that together form a paragraph.
30
+ It splits content into lines that fit within max_width by measuring rendered width.
31
+ Each line is a separate Text object joined into a VGroup and arranged downward.
32
+ """
33
+ words = content.split()
34
+ lines = []
35
+ current = ""
36
+
37
+ # Create a temporary Text to measure width; use the same font/size as final lines
38
+ temp = Text("", color=color, font=font, font_size=font_size)
39
+
40
+ for w in words:
41
+ test = w if not current else current + " " + w
42
+ test_obj = Text(test, color=color, font=font, font_size=font_size)
43
+ if test_obj.width <= max_width:
44
+ current = test
45
+ else:
46
+ # flush the current line
47
+ line = Text(current, color=color, font=font, font_size=font_size)
48
+ lines.append(line)
49
+ current = w
50
+ if current:
51
+ lines.append(Text(current, color=color, font=font, font_size=font_size))
52
+
53
+ if not lines:
54
+ return VGroup()
55
+
56
+ para = VGroup(*lines)
57
+ # Space lines vertically; arrange them as a column
58
+ para.arrange(DOWN, buff=line_spacing)
59
+ if align_left:
60
+ para = para.align_to(LEFT)
61
+ return para
62
+
63
  def create_manim_script(problem_data, script_path):
64
+ """Generate Manim script from problem data with robust wrapping for title, text, and equations."""
65
+
66
+ # Defaults
67
  settings = problem_data.get("video_settings", {
68
  "background_color": "#0f0f23",
69
  "text_color": "WHITE",
 
71
  "font": "CMU Serif",
72
  "text_size": 36,
73
  "equation_size": 42,
74
+ "title_size": 48,
75
+ "wrap_width": 12.0 # in scene width units; adjust to taste
76
  })
77
+
78
  slides = problem_data.get("slides", [])
79
  if not slides:
80
  raise ValueError("No slides provided in input data")
81
+
82
  slides_repr = repr(slides)
83
+
84
+ # Use a dedicated wrap width in scene units; you can adapt how max_width is computed
85
+ wrap_width = float(settings.get("wrap_width", 12.0))
86
+
87
  manim_code = f'''
88
  from manim import *
89
  import textwrap
 
90
  class GeneratedMathScene(Scene):
91
  def construct(self):
92
+ # Scene settings
93
  self.camera.background_color = "{settings.get('background_color', '#0f0f23')}"
94
  default_color = {settings.get('text_color', 'WHITE')}
95
  highlight_color = {settings.get('highlight_color', 'YELLOW')}
 
97
  text_size = {settings.get('text_size', 36)}
98
  equation_size = {settings.get('equation_size', 42)}
99
  title_size = {settings.get('title_size', 48)}
100
+ wrap_width = {wrap_width}
101
 
102
+ # Helper to wrap text into lines that fit within max width
103
+ def make_wrapped_paragraph(content, color, font, font_size, line_spacing=0.2):
104
+ lines = []
105
+ words = content.split()
106
+ current = ""
107
+ for w in words:
108
+ test = w if not current else current + " " + w
109
+ test_obj = Text(test, color=color, font=font, font_size=font_size)
110
+ if test_obj.width <= wrap_width * 0.9: # a bit of padding
111
+ current = test
112
+ else:
113
+ lines.append(Text(current, color=color, font=font, font_size=font_size))
114
+ current = w
115
+ if current:
116
+ lines.append(Text(current, color=color, font=font, font_size=font_size))
117
+ if not lines:
118
+ return VGroup()
119
+ para = VGroup(*lines).arrange(DOWN, buff=line_spacing)
120
+ return para
121
+
122
+ class GeneratedMathSceneInner(Scene):
123
+ pass
124
+
125
  content_group = VGroup()
126
  current_y = 3.0
127
  line_spacing = 0.8
128
+
 
129
  slides = {slides_repr}
130
 
131
+ # Build each slide
132
  for idx, slide in enumerate(slides):
133
  obj = None
134
  content = slide.get("content", "")
 
137
  slide_type = slide.get("type", "text")
138
 
139
  if slide_type == "title":
140
+ # Wrap title text
141
+ title_text = content
142
+ # Use paragraph wrapping to keep multi-line titles readable
143
+ lines = []
144
+ if title_text:
145
+ lines = []
146
+ # Reuse make_wrapped_paragraph by simulating a single paragraph
147
+ lines_group = make_wrapped_paragraph(title_text, highlight_color, default_font, title_size, line_spacing=0.2)
148
+ obj = lines_group if len(lines_group) > 0 else Text(title_text, color=highlight_color, font=default_font, font_size=title_size)
149
+ else:
150
+ obj = Text("", color=highlight_color, font=default_font, font_size=title_size)
151
+ if obj.width > wrap_width:
152
+ obj.scale_to_fit_width(wrap_width)
153
+
154
  obj.move_to(ORIGIN)
155
  self.play(FadeIn(obj), run_time=duration * 0.8)
156
  self.wait(duration * 0.3)
 
158
  continue
159
 
160
  elif slide_type == "text":
161
+ # Use wrapping for normal text
162
+ obj = make_wrapped_paragraph(content, default_color, default_font, text_size, line_spacing=0.25)
 
 
 
 
 
 
163
 
164
  elif slide_type == "equation":
165
+ # Wrap long equations by splitting content into lines if needed
166
+ # Heuristic: if content is too wide, create a multi-line TeX using \\ line breaks
167
+ eq_content = content
168
+ # Optional: insert line breaks at common math breakpoints if needed
169
+ test = MathTex(eq_content, color=default_color, font_size=equation_size)
170
+ if test.width > wrap_width:
171
+ # naive wrap: insert line breaks at spaces near the middle
172
+ parts = eq_content.split(" ")
173
+ mid = len(parts)//2
174
+ line1 = " ".join(parts[:mid])
175
+ line2 = " ".join(parts[mid:])
176
+ wrapped_eq = f"{line1} \\\\ {line2}"
177
+ obj = MathTex(wrapped_eq, color=default_color, font_size=equation_size)
178
+ else:
179
+ obj = MathTex(eq_content, color=default_color, font_size=equation_size)
180
+
181
+ if obj.width > wrap_width:
182
+ obj.scale_to_fit_width(wrap_width)
183
 
184
  if obj:
185
+ # Position and animate
186
  obj.to_edge(LEFT, buff=0.3)
187
  obj.shift(UP * (current_y - obj.height/2))
188
 
189
  obj_bottom = obj.get_bottom()[1]
190
+ if obj_bottom < -3.5:
191
+ scroll_amount = abs(obj_bottom - (-3.5)) + 0.3
192
  self.play(content_group.animate.shift(UP * scroll_amount), run_time=0.5)
193
  current_y += scroll_amount
194
  obj.shift(UP * scroll_amount)
 
204
  self.play(Write(obj), run_time=duration)
205
 
206
  content_group.add(obj)
207
+ # Decrease y for next item
208
+ current_y -= (getattr(obj, "height", 0) + line_spacing)
209
  self.wait(0.3)
210
 
211
  if len(content_group) > 0:
212
  final_box = SurroundingRectangle(content_group[-1], color=highlight_color, buff=0.2)
213
  self.play(Create(final_box), run_time=0.8)
214
  self.wait(1.5)
215
+ '''
216
+
217
  with open(script_path, 'w', encoding='utf-8') as f:
218
  f.write(manim_code)
219