", unsafe_allow_html=True)
preview_html = generate_manim_preview(st.session_state.code)
components.html(preview_html, height=250)
st.markdown("
", unsafe_allow_html=True)
# Generated output display
if st.session_state.video_data:
# Different handling based on format type
format_type = st.session_state.settings["format_type"]
if format_type == "png_sequence":
st.info("PNG sequence generated successfully. Use the download button to get the ZIP file.")
# Add download button for ZIP
st.download_button(
label="âŦī¸ Download PNG Sequence (ZIP)",
data=st.session_state.video_data,
file_name=f"manim_pngs_{datetime.now().strftime('%Y%m%d_%H%M%S')}.zip",
mime="application/zip",
use_container_width=True
)
elif format_type == "svg":
# Display SVG preview
try:
svg_data = st.session_state.video_data.decode('utf-8')
components.html(svg_data, height=400)
except Exception as e:
st.error(f"Error displaying SVG: {str(e)}")
# Download button for SVG
st.download_button(
label="âŦī¸ Download SVG",
data=st.session_state.video_data,
file_name=f"manim_animation_{datetime.now().strftime('%Y%m%d_%H%M%S')}.svg",
mime="image/svg+xml",
use_container_width=True
)
else:
# Standard video display for MP4, GIF, WebM
try:
st.video(st.session_state.video_data, format=format_type)
except Exception as e:
st.error(f"Error displaying video: {str(e)}")
# Fallback for GIF if st.video fails
if format_type == "gif":
st.markdown("GIF preview:")
gif_b64 = base64.b64encode(st.session_state.video_data).decode()
st.markdown(f'", unsafe_allow_html=True)
st.markdown("#### Generate Animation from Description")
st.write("Describe the animation you want to create, or provide partial code to complete.")
# Predefined animation ideas dropdown
animation_ideas = [
"Select an idea...",
"Create a 3D animation showing a sphere morphing into a torus",
"Show a visual proof of the Pythagorean theorem",
"Visualize a Fourier transform converting a signal from time domain to frequency domain",
"Create an animation explaining neural network forward propagation",
"Illustrate the concept of integration with area under a curve"
]
selected_idea = st.selectbox(
"Try one of these ideas",
options=animation_ideas
)
prompt_value = selected_idea if selected_idea != "Select an idea..." else ""
code_input = st.text_area(
"Your Prompt or Code",
value=prompt_value,
placeholder="Example: Create an animation that shows a circle morphing into a square while changing color from red to blue",
height=150
)
if st.button("Generate Animation Code", key="gen_ai_code"):
if code_input:
with st.spinner("AI is generating your animation code..."):
try:
# Get the client and model name
client = st.session_state.ai_models["client"]
model_name = st.session_state.ai_models["model_name"]
# Create the prompt
prompt = f"""Write a complete Manim animation scene based on this code or idea:
{code_input}
The code should be a complete, working Manim animation that includes:
- Proper Scene class definition
- Constructor with animations
- Proper use of self.play() for animations
- Proper wait times between animations
Here's the complete Manim code:
"""
# Prepare API parameters
from azure.ai.inference.models import UserMessage
messages = [UserMessage(prompt)]
api_params, config = prepare_api_params(messages, model_name)
# Make the API call with proper parameters
response = client.complete(**api_params)
# Process the response
if response and response.choices and len(response.choices) > 0:
completed_code = response.choices[0].message.content
# Extract code from markdown if present
if "```python" in completed_code:
completed_code = completed_code.split("```python")[1].split("```")[0]
elif "```" in completed_code:
completed_code = completed_code.split("```")[1].split("```")[0]
# Add Scene class if missing
if "Scene" not in completed_code:
completed_code = f"""from manim import *
class MyScene(Scene):
def construct(self):
{completed_code}"""
# Store the generated code
st.session_state.generated_code = completed_code
else:
st.error("Failed to generate code. API returned an empty response.")
except Exception as e:
st.error(f"Error generating code: {str(e)}")
import traceback
st.code(traceback.format_exc())
else:
st.warning("Please enter a description or prompt first")
# AI generated code display and actions
if "generated_code" in st.session_state and st.session_state.generated_code:
st.markdown("
", unsafe_allow_html=True)
st.markdown("#### Generated Animation Code")
st.code(st.session_state.generated_code, language="python")
col_ai1, col_ai2 = st.columns(2)
with col_ai1:
if st.button("Use This Code", key="use_gen_code"):
st.session_state.code = st.session_state.generated_code
st.session_state.temp_code = st.session_state.generated_code
# Set pending tab switch to editor tab
st.session_state.pending_tab_switch = 0
st.rerun()
with col_ai2:
if st.button("Render Preview", key="render_preview"):
with st.spinner("Rendering preview..."):
video_data, status = generate_manim_video(
st.session_state.generated_code,
"mp4",
"480p", # Use lowest quality for preview
ANIMATION_SPEEDS["Normal"],
fps=st.session_state.settings["fps"]
)
if video_data:
st.video(video_data)
st.download_button(
label="Download Preview",
data=video_data,
file_name=f"manim_preview_{int(time.time())}.mp4",
mime="video/mp4"
)
else:
st.error(f"Failed to generate preview: {status}")
st.markdown("
", unsafe_allow_html=True)
else:
st.warning("AI models not initialized. Please use the Debug Connection section to test API connectivity.")
else:
st.info("Please enter the correct password to access AI features")
# ASSETS TAB
with tabs[2]:
st.markdown("### đ¨ Asset Management")
asset_col1, asset_col2 = st.columns([1, 1])
with asset_col1:
# Image uploader section
st.markdown("#### đ¸ Image Assets")
st.markdown("Upload images to use in your animations:")
# Allow multiple image uploads
uploaded_images = st.file_uploader(
"Upload Images",
type=["jpg", "png", "jpeg", "svg"],
accept_multiple_files=True,
key="image_uploader_tab"
)
if uploaded_images:
# Create a unique image directory if it doesn't exist
image_dir = os.path.join(os.getcwd(), "manim_assets", "images")
os.makedirs(image_dir, exist_ok=True)
# Process each uploaded image
for uploaded_image in uploaded_images:
# Generate a unique filename and save the image
file_extension = uploaded_image.name.split(".")[-1]
unique_filename = f"image_{int(time.time())}_{uuid.uuid4().hex[:8]}.{file_extension}"
image_path = os.path.join(image_dir, unique_filename)
with open(image_path, "wb") as f:
f.write(uploaded_image.getvalue())
# Store the path in session state
if "image_paths" not in st.session_state:
st.session_state.image_paths = []
# Check if this image was already added
image_already_added = False
for img in st.session_state.image_paths:
if img["name"] == uploaded_image.name:
image_already_added = True
break
if not image_already_added:
st.session_state.image_paths.append({
"name": uploaded_image.name,
"path": image_path
})
# Display uploaded images in a grid
st.markdown("##### Uploaded Images:")
image_cols = st.columns(3)
for i, img_info in enumerate(st.session_state.image_paths[-len(uploaded_images):]):
with image_cols[i % 3]:
try:
img = Image.open(img_info["path"])
st.image(img, caption=img_info["name"], width=150)
# Show code snippet for this specific image
if st.button(f"Use {img_info['name']}", key=f"use_img_{i}"):
image_code = f"""
# Load and display image
image = ImageMobject(r"{img_info['path']}")
image.scale(2) # Adjust size as needed
self.play(FadeIn(image))
self.wait(1)
"""
if not st.session_state.code:
base_code = """from manim import *
class ImageScene(Scene):
def construct(self):
"""
st.session_state.code = base_code + "\n " + image_code.replace("\n", "\n ")
else:
st.session_state.code += "\n" + image_code
st.session_state.temp_code = st.session_state.code
st.success(f"Added {img_info['name']} to your code!")
# Set pending tab switch to editor tab
st.session_state.pending_tab_switch = 0
st.rerun()
except Exception as e:
st.error(f"Error loading image {img_info['name']}: {e}")
# Display previously uploaded images
if st.session_state.image_paths:
with st.expander("Previously Uploaded Images"):
# Group images by 3 in each row
for i in range(0, len(st.session_state.image_paths), 3):
prev_cols = st.columns(3)
for j in range(3):
if i+j < len(st.session_state.image_paths):
img_info = st.session_state.image_paths[i+j]
with prev_cols[j]:
try:
img = Image.open(img_info["path"])
st.image(img, caption=img_info["name"], width=100)
st.markdown(f"
Path: {img_info['path']}
", unsafe_allow_html=True)
except:
st.markdown(f"**{img_info['name']}**")
st.markdown(f"
Path: {img_info['path']}
", unsafe_allow_html=True)
with asset_col2:
# Audio uploader section
st.markdown("#### đĩ Audio Assets")
st.markdown("Upload audio files for background or narration:")
uploaded_audio = st.file_uploader("Upload Audio", type=["mp3", "wav", "ogg"], key="audio_uploader")
if uploaded_audio:
# Create a unique audio directory if it doesn't exist
audio_dir = os.path.join(os.getcwd(), "manim_assets", "audio")
os.makedirs(audio_dir, exist_ok=True)
# Generate a unique filename and save the audio
file_extension = uploaded_audio.name.split(".")[-1]
unique_filename = f"audio_{int(time.time())}.{file_extension}"
audio_path = os.path.join(audio_dir, unique_filename)
with open(audio_path, "wb") as f:
f.write(uploaded_audio.getvalue())
# Store the path in session state
st.session_state.audio_path = audio_path
# Display audio player
st.audio(uploaded_audio)
st.markdown(f"""
Audio: {uploaded_audio.name}
Path: {audio_path}
""", unsafe_allow_html=True)
# Two options for audio usage
st.markdown("#### Add Audio to Your Animation")
option = st.radio(
"Choose how to use audio:",
["Background Audio", "Generate Audio from Text"]
)
if option == "Background Audio":
st.markdown("##### Code to add background audio:")
# For with_sound decorator
audio_code1 = f"""
# Add this import at the top of your file
from manim.scene.scene_file_writer import SceneFileWriter
# Add this decorator before your scene class
@with_sound("{audio_path}")
class YourScene(Scene):
def construct(self):
# Your animation code here
"""
st.code(audio_code1, language="python")
if st.button("Use This Audio in Animation", key="use_audio_btn"):
st.success("Audio set for next render!")
elif option == "Generate Audio from Text":
# Text-to-speech input
tts_text = st.text_area(
"Enter text for narration",
placeholder="Type the narration text here...",
height=100
)
if st.button("Create Narration", key="create_narration_btn"):
try:
# Use basic TTS (placeholder for actual implementation)
st.warning("Text-to-speech feature requires additional setup. Using uploaded audio instead.")
st.session_state.audio_path = audio_path
st.success("Audio set for next render!")
except Exception as e:
st.error(f"Error creating narration: {str(e)}")
# TIMELINE EDITOR TAB
with tabs[3]:
# New code for reordering animation steps
updated_code = create_timeline_editor(st.session_state.code)
# If code was modified by the timeline editor, update the session state
if updated_code != st.session_state.code:
st.session_state.code = updated_code
st.session_state.temp_code = updated_code
# EDUCATIONAL EXPORT TAB
with tabs[4]:
st.markdown("### đ Educational Export Options")
# Check if we have an animation to export
if not st.session_state.video_data:
st.warning("Generate an animation first before using educational export features.")
else:
st.markdown("Create various educational assets from your animation:")
# Animation title and explanation
animation_title = st.text_input("Animation Title", value="Manim Animation", key="edu_title")
st.markdown("#### Explanation Text")
st.markdown("Add explanatory text to accompany your animation. Use markdown formatting.")
st.markdown("Use ## to separate explanation sections for step-by-step sequence export.")
explanation_text = st.text_area(
"Explanation (markdown supported)",
height=150,
placeholder="Explain your animation here...\n\n## Step 1\nIntroduction to the concept...\n\n## Step 2\nNext, we demonstrate..."
)
# Export format selection
edu_format = st.selectbox(
"Export Format",
options=["PowerPoint Presentation", "Interactive HTML", "Explanation Sequence PDF"]
)
# Format-specific options
if edu_format == "PowerPoint Presentation":
st.info("Creates a PowerPoint file with your animation and explanation text.")
elif edu_format == "Interactive HTML":
st.info("Creates an interactive HTML webpage with playback controls and explanation.")
include_controls = st.checkbox("Include interactive controls", value=True)
elif edu_format == "Explanation Sequence PDF":
st.info("Creates a PDF with key frames and step-by-step explanations.")
frame_count = st.slider("Number of key frames", min_value=3, max_value=10, value=5)
# Export button
if st.button("Export Educational Material", key="export_edu_btn"):
with st.spinner(f"Creating {edu_format}..."):
# Map selected format to internal format type
format_map = {
"PowerPoint Presentation": "powerpoint",
"Interactive HTML": "html",
"Explanation Sequence PDF": "sequence"
}
# Create a temporary directory for export
temp_export_dir = tempfile.mkdtemp(prefix="manim_edu_export_")
# Process the export
exported_data, file_type = export_to_educational_format(
st.session_state.video_data,
format_map[edu_format],
animation_title,
explanation_text,
temp_export_dir
)
if exported_data:
# File extension mapping
ext_map = {
"powerpoint": "pptx",
"html": "html",
"pdf": "pdf"
}
# Download button
ext = ext_map.get(file_type, "zip")
filename = f"{animation_title.replace(' ', '_')}.{ext}"
st.success(f"{edu_format} created successfully!")
st.download_button(
label=f"âŦī¸ Download {edu_format}",
data=exported_data,
file_name=filename,
mime=f"application/{ext}",
use_container_width=True
)
# For HTML, also offer to open in browser
if file_type == "html":
html_path = os.path.join(temp_export_dir, filename)
st.markdown(f"[đ Open in browser](file://{html_path})", unsafe_allow_html=True)
else:
st.error(f"Failed to create {edu_format}. Check logs for details.")
# Show usage examples and tips
with st.expander("Usage Tips"):
st.markdown("""
### Educational Export Tips
**PowerPoint Presentations**
- Great for lectures and classroom presentations
- Animation will autoplay when clicked
- Add detailed explanations in notes section
**Interactive HTML**
- Perfect for websites and online learning platforms
- Students can control playback speed and navigation
- Mobile-friendly for learning on any device
**Explanation Sequence**
- Ideal for printed materials and study guides
- Use ## headers to mark different explanation sections
- Each section will be paired with a key frame
""")
# PYTHON RUNNER TAB
with tabs[5]:
st.markdown("### đ Python Script Runner")
st.markdown("Execute Python scripts and visualize the results directly.")
# New UI elements for advanced features
with st.expander("đ§ Advanced Python Features"):
py_feature_col1, py_feature_col2 = st.columns(2)
with py_feature_col1:
enable_debugging = st.checkbox("Enable Debugging", value=False, key="py_debug_enable")
enable_profiling = st.checkbox("Enable Profiling", value=False, key="py_profile_enable")
with py_feature_col2:
py_libs = st.multiselect(
"Additional Libraries",
options=["numpy", "scipy", "pandas", "matplotlib", "seaborn", "plotly", "scikit-learn", "tensorflow", "pytorch", "sympy"],
default=["numpy", "matplotlib"],
key="py_additional_libs"
)
# Multi-file project support
with st.expander("đ Multi-file Project"):
st.markdown("Add multiple Python files to your project")
# File manager
if "py_project_files" not in st.session_state:
st.session_state.py_project_files = {"main.py": st.session_state.python_script}
# File selector
current_file = st.selectbox(
"Select File",
options=list(st.session_state.py_project_files.keys()),
key="py_current_file"
)
# New file creation
new_file_col1, new_file_col2 = st.columns([3, 1])
with new_file_col1:
new_filename = st.text_input("New File Name", value="", key="py_new_filename")
with new_file_col2:
if st.button("Add File", key="py_add_file_btn"):
if new_filename and new_filename not in st.session_state.py_project_files:
if not new_filename.endswith(".py"):
new_filename += ".py"
st.session_state.py_project_files[new_filename] = "# New Python file\n\n"
st.session_state.py_current_file = new_filename
st.experimental_rerun()
# Update the current file content in session state
if current_file in st.session_state.py_project_files:
st.session_state.py_project_files[current_file] = st.session_state.python_script
# Update main script if we're editing the main file
if current_file == "main.py":
st.session_state.python_script = st.session_state.python_script
# Real-time visualization toggle
real_time_viz = st.checkbox("Enable Real-time Visualization", value=False, key="py_realtime_viz")
# Predefined example scripts
example_scripts = {
"Select an example...": "",
"Basic Matplotlib Plot": """import matplotlib.pyplot as plt
import numpy as np
# Create data
x = np.linspace(0, 10, 100)
y = np.sin(x)
# Create plot
plt.figure(figsize=(10, 6))
plt.plot(x, y, 'b-', label='sin(x)')
plt.title('Sine Wave')
plt.xlabel('x')
plt.ylabel('sin(x)')
plt.grid(True)
plt.legend()
""",
"User Input Example": """# This example demonstrates how to handle user input
name = input("Enter your name: ")
age = int(input("Enter your age: "))
print(f"Hello, {name}! In 10 years, you'll be {age + 10} years old.")
# Let's get some numbers and calculate the average
num_count = int(input("How many numbers would you like to average? "))
total = 0
for i in range(num_count):
num = float(input(f"Enter number {i+1}: "))
total += num
average = total / num_count
print(f"The average of your {num_count} numbers is: {average}")
""",
"Pandas DataFrame": """import pandas as pd
import numpy as np
# Create a sample dataframe
data = {
'Name': ['Alice', 'Bob', 'Charlie', 'David', 'Emma'],
'Age': [25, 30, 35, 40, 45],
'Salary': [50000, 60000, 70000, 80000, 90000],
'Department': ['HR', 'IT', 'Finance', 'Marketing', 'Engineering']
}
df = pd.DataFrame(data)
# Display the dataframe
print("Sample DataFrame:")
print(df)
# Basic statistics
print("\\nSummary Statistics:")
print(df.describe())
# Filtering
print("\\nEmployees older than 30:")
print(df[df['Age'] > 30])
""",
"Seaborn Visualization": """import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
import pandas as pd
# Set the style
sns.set_style("whitegrid")
# Create sample data
np.random.seed(42)
data = np.random.randn(100, 3)
df = pd.DataFrame(data, columns=['A', 'B', 'C'])
df['category'] = pd.Categorical(['Group 1'] * 50 + ['Group 2'] * 50)
# Create a paired plot
sns.pairplot(df, hue='category', palette='viridis')
# Create another plot
plt.figure(figsize=(10, 6))
sns.violinplot(x='category', y='A', data=df, palette='magma')
plt.title('Distribution of A by Category')
"""
}
# Select example script
selected_example = st.selectbox("Select an example script:", options=list(example_scripts.keys()))
# Python code editor
if selected_example != "Select an example..." and selected_example in example_scripts:
python_code = example_scripts[selected_example]
else:
python_code = st.session_state.python_script
if ACE_EDITOR_AVAILABLE:
python_code = st_ace(
value=python_code,
language="python",
theme="monokai",
min_lines=15,
key=f"python_editor_{st.session_state.editor_key}"
)
else:
python_code = st.text_area(
"Python Code",
value=python_code,
height=400,
key=f"python_textarea_{st.session_state.editor_key}"
)
# Store script in session state (without clearing existing code)
st.session_state.python_script = python_code
# Check for input() calls
input_calls = detect_input_calls(python_code)
user_inputs = []
if input_calls:
st.markdown("### Input Values")
st.info(f"This script contains {len(input_calls)} input() calls. Please provide values below:")
for i, input_call in enumerate(input_calls):
user_input = st.text_input(
f"{input_call['prompt']} (Line {input_call['line']})",
key=f"input_{i}"
)
user_inputs.append(user_input)
# Options and execution
col1, col2 = st.columns([2, 1])
with col1:
timeout_seconds = st.slider("Execution Timeout (seconds)", 5, 3600, 30)
with col2:
run_btn = st.button("âļī¸ Run Script", use_container_width=True)
if run_btn:
with st.spinner("Executing Python script..."):
# Use the enhanced function
result = run_python_script_enhanced(
python_code,
inputs=user_inputs,
timeout=timeout_seconds,
enable_debug=enable_debugging,
enable_profile=enable_profiling,
additional_libs=py_libs,
project_files=st.session_state.py_project_files if "py_project_files" in st.session_state else None,
realtime_viz=real_time_viz
)
st.session_state.python_result = result
# Display results
if st.session_state.python_result:
display_python_script_results_enhanced(st.session_state.python_result)
# Provide option to save the script
if st.button("đ Save This Script", key="save_script_btn"):
# Generate a unique filename
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
script_filename = f"script_{timestamp}.py"
# Offer download button for the script
st.download_button(
label="âŦī¸ Download Script",
data=python_code,
file_name=script_filename,
mime="text/plain"
)
# Show advanced examples and tips
with st.expander("Python Script Runner Tips"):
st.markdown("""
### Python Script Runner Tips
**What can I run?**
- Any Python code that doesn't require direct UI interaction
- Libraries like Matplotlib, NumPy, Pandas, SciPy, etc.
- Data processing and visualization code
- Scripts that ask for user input (now supported!)
**What can't I run?**
- Streamlit, Gradio, Dash, or other web UIs
- Long-running operations (timeout will occur)
- Code that requires file access outside the temporary environment
**Working with visualizations:**
- All Matplotlib/Seaborn plots will be automatically captured
- Pandas DataFrames are detected and displayed as tables
- Use `print()` to show text output
**Handling user input:**
- The app detects input() calls and automatically creates text fields
- Input values you provide will be passed to the script when it runs
- Type conversion (like int(), float()) is preserved
**Adding to animations:**
- Charts and plots can be directly added to your Manim animations
- Generated images will be properly scaled for your animation
- Perfect for educational content combining data and animations
""")
# C/C++ RUNNER TAB
with tabs[6]: # Assuming this is the 7th tab (index 6)
st.markdown("### đ§ C/C++ Runner")
st.markdown("Write, compile, and run C/C++ code with advanced features.")
# Create a tabbed interface for different C++ features
cpp_tabs = st.tabs(["Code Editor", "Project Files", "Libraries", "Build Settings", "Debugger"])
with cpp_tabs[0]: # Code Editor tab
# Compiler options
cpp_col1, cpp_col2, cpp_col3 = st.columns(3)
with cpp_col1:
compiler = st.selectbox(
"Compiler",
options=["g++", "clang++", "gcc", "msvc"],
index=["g++", "clang++", "gcc", "msvc"].index(st.session_state.cpp_settings["compiler"]),
key="cpp_compiler"
)
st.session_state.cpp_settings["compiler"] = compiler
with cpp_col2:
std_version = st.selectbox(
"Standard",
options=["c++11", "c++14", "c++17", "c++20"],
index=["c++11", "c++14", "c++17", "c++20"].index(st.session_state.cpp_settings["std"]),
key="cpp_std"
)
st.session_state.cpp_settings["std"] = std_version
with cpp_col3:
optimization = st.selectbox(
"Optimization",
options=["-O0", "-O1", "-O2", "-O3"],
index=["-O0", "-O1", "-O2", "-O3"].index(st.session_state.cpp_settings["optimization"]),
key="cpp_opt"
)
st.session_state.cpp_settings["optimization"] = optimization
# Example code templates
cpp_examples = {
"Select an example...": "",
"Hello World": """#include
int main() {
std::cout << "Hello, World!" << std::endl;
return 0;
}""",
"Calculate Prime Numbers": """#include
#include
#include
bool isPrime(int n) {
if (n <= 1) return false;
if (n <= 3) return true;
if (n % 2 == 0 || n % 3 == 0) return false;
for (int i = 5; i * i <= n; i += 6) {
if (n % i == 0 || n % (i + 2) == 0)
return false;
}
return true;
}
int main() {
int limit = 10000;
std::vector primes;
auto start = std::chrono::high_resolution_clock::now();
for (int i = 2; i <= limit; i++) {
if (isPrime(i)) {
primes.push_back(i);
}
}
auto end = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast(end - start);
std::cout << "Found " << primes.size() << " prime numbers up to " << limit << std::endl;
std::cout << "First 10 primes: ";
for (int i = 0; i < std::min(10, (int)primes.size()); i++) {
std::cout << primes[i] << " ";
}
std::cout << std::endl;
std::cout << "Computation time: " << duration.count() << " ms" << std::endl;
return 0;
}""",
"Image Generation (PPM)": """#include
#include
#include
// Generate a simple gradient image in PPM format
int main() {
const int width = 800;
const int height = 600;
// Create a PPM file (P3 format - ASCII)
std::ofstream image("output.ppm");
image << "P3\\n" << width << " " << height << "\\n255\\n";
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
// Create a gradient based on position
int r = static_cast(255.0 * x / width);
int g = static_cast(255.0 * y / height);
int b = static_cast(255.0 * (x + y) / (width + height));
// Write RGB values
image << r << " " << g << " " << b << "\\n";
}
}
image.close();
std::cout << "Generated gradient image: output.ppm" << std::endl;
return 0;
}""",
"Data Processing with Vectors": """#include
#include
#include
#include
#include
#include
int main() {
const int data_size = 1000;
// Generate random data
std::vector data(data_size);
std::random_device rd;
std::mt19937 gen(rd());
std::normal_distribution dist(100.0, 15.0);
std::cout << "Generating " << data_size << " random values..." << std::endl;
for (auto& value : data) {
value = dist(gen);
}
// Calculate statistics
double sum = std::accumulate(data.begin(), data.end(), 0.0);
double mean = sum / data.size();
std::vector deviations(data_size);
std::transform(data.begin(), data.end(), deviations.begin(),
[mean](double x) { return x - mean; });
double sq_sum = std::inner_product(deviations.begin(), deviations.end(),
deviations.begin(), 0.0);
double stddev = std::sqrt(sq_sum / data.size());
// Sort data
std::sort(data.begin(), data.end());
double median = data.size() % 2 == 0 ?
(data[data.size()/2 - 1] + data[data.size()/2]) / 2 :
data[data.size()/2];
// Output results
std::cout << std::fixed << std::setprecision(2);
std::cout << "Data analysis results:" << std::endl;
std::cout << "Mean: " << mean << std::endl;
std::cout << "Median: " << median << std::endl;
std::cout << "StdDev: " << stddev << std::endl;
std::cout << "Min: " << data.front() << std::endl;
std::cout << "Max: " << data.back() << std::endl;
return 0;
}""",
"Interactive User Input": """#include
#include
#include
int main() {
std::string name;
int age;
// Get user input
std::cout << "Enter your name: ";
std::getline(std::cin, name);
std::cout << "Enter your age: ";
std::cin >> age;
std::cin.ignore(); // Clear the newline from the buffer
std::cout << "Hello, " << name << "! ";
std::cout << "In 10 years, you will be " << age + 10 << " years old." << std::endl;
// Get multiple numbers
int num_count;
std::cout << "How many numbers would you like to enter? ";
std::cin >> num_count;
std::vector numbers;
double total = 0.0;
for (int i = 0; i < num_count; i++) {
double num;
std::cout << "Enter number " << (i+1) << ": ";
std::cin >> num;
numbers.push_back(num);
total += num;
}
if (!numbers.empty()) {
double average = total / numbers.size();
std::cout << "The average of your numbers is: " << average << std::endl;
}
return 0;
}""",
"Eigen Matrix Operations": """#include
#include
using Eigen::MatrixXd;
using Eigen::VectorXd;
int main() {
// Create a 3x3 matrix
MatrixXd A(3, 3);
A << 1, 2, 3,
4, 5, 6,
7, 8, 9;
// Create a 3D vector
VectorXd b(3);
b << 1, 2, 3;
// Perform operations
std::cout << "Matrix A:\\n" << A << std::endl;
std::cout << "Vector b:\\n" << b << std::endl;
std::cout << "A * b:\\n" << A * b << std::endl;
std::cout << "A transpose:\\n" << A.transpose() << std::endl;
// Solve a linear system Ax = b
VectorXd x = A.colPivHouseholderQr().solve(b);
std::cout << "Solution to Ax = b:\\n" << x << std::endl;
// Compute eigenvalues and eigenvectors
Eigen::EigenSolver solver(A);
std::cout << "Eigenvalues:\\n" << solver.eigenvalues() << std::endl;
std::cout << "Eigenvectors:\\n" << solver.eigenvectors() << std::endl;
return 0;
}""",
"OpenCV Image Processing": """#include
#include
int main() {
// Load an image (this will create a blank image if no file is found)
cv::Mat image = cv::Mat::zeros(500, 500, CV_8UC3);
// Draw a circle
cv::circle(image, cv::Point(250, 250), 100, cv::Scalar(0, 0, 255), 5);
// Draw a rectangle
cv::rectangle(image, cv::Point(150, 150), cv::Point(350, 350), cv::Scalar(0, 255, 0), 3);
// Add text
cv::putText(image, "OpenCV Example", cv::Point(100, 50), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(255, 255, 255), 2);
// Save the image
cv::imwrite("opencv_output.png", image);
std::cout << "Image created and saved as 'opencv_output.png'" << std::endl;
return 0;
}"""
}
# Example selection
selected_cpp_example = st.selectbox("Example code:", options=list(cpp_examples.keys()))
# Set initial code from example or session state
if selected_cpp_example != "Select an example..." and cpp_examples[selected_cpp_example] != "":
initial_code = cpp_examples[selected_cpp_example]
else:
if "cpp_current_file" in st.session_state and st.session_state.cpp_current_file in st.session_state.cpp_project_files:
initial_code = st.session_state.cpp_project_files[st.session_state.cpp_current_file]
else:
initial_code = st.session_state.cpp_code
# Code editor for C++
if ACE_EDITOR_AVAILABLE:
cpp_code = st_ace(
value=initial_code,
language="c_cpp",
theme="monokai",
min_lines=15,
key=f"cpp_editor_{st.session_state.editor_key}"
)
else:
cpp_code = st.text_area(
"C/C++ Code",
value=initial_code,
height=400,
key=f"cpp_textarea_{st.session_state.editor_key}"
)
# Save the code to session state
st.session_state.cpp_code = cpp_code
# Update project files
if "cpp_current_file" in st.session_state and st.session_state.cpp_current_file in st.session_state.cpp_project_files:
st.session_state.cpp_project_files[st.session_state.cpp_current_file] = cpp_code
# Check for standard input in the code
has_cin = "std::cin" in cpp_code or "cin" in cpp_code
# Input values section if needed
cpp_inputs = []
if has_cin:
with st.expander("Input Values"):
st.info("This program uses standard input. Please provide input values below:")
num_inputs = st.number_input("Number of input lines:", min_value=1, max_value=10, value=1)
for i in range(int(num_inputs)):
cpp_input = st.text_input(f"Input line {i+1}:", key=f"cpp_input_{i}")
cpp_inputs.append(cpp_input)
with cpp_tabs[1]: # Project Files tab
st.markdown("### Project Files")
st.markdown("Manage multiple source files for your C/C++ project")
# File selector
cpp_current_file = st.selectbox(
"Current File",
options=list(st.session_state.cpp_project_files.keys()),
index=list(st.session_state.cpp_project_files.keys()).index(st.session_state.cpp_current_file) if "cpp_current_file" in st.session_state else 0,
key="cpp_file_selector"
)
# Update the current file in session state
st.session_state.cpp_current_file = cpp_current_file
# Create new file form
new_file_col1, new_file_col2 = st.columns([3, 1])
with new_file_col1:
new_cpp_filename = st.text_input("New File Name", placeholder="e.g., utils.h, helper.cpp", key="new_cpp_file")
with new_file_col2:
if st.button("Add File", key="add_cpp_file"):
if new_cpp_filename and new_cpp_filename not in st.session_state.cpp_project_files:
# Add file extension if missing
if not new_cpp_filename.endswith((".cpp", ".h", ".hpp", ".c", ".cc")):
new_cpp_filename += ".cpp"
# Create a template based on file type
if new_cpp_filename.endswith((".h", ".hpp")):
template = f"""#ifndef {new_cpp_filename.split('.')[0].upper()}_H
#define {new_cpp_filename.split('.')[0].upper()}_H
// Your header content here
#endif // {new_cpp_filename.split('.')[0].upper()}_H
"""
else:
template = f"""#include
// Your implementation here
"""
st.session_state.cpp_project_files[new_cpp_filename] = template
st.session_state.cpp_current_file = new_cpp_filename
st.experimental_rerun()
# File actions
file_action_col1, file_action_col2 = st.columns(2)
with file_action_col1:
if st.button("Delete Current File", key="delete_cpp_file"):
if cpp_current_file != "main.cpp" and cpp_current_file in st.session_state.cpp_project_files:
del st.session_state.cpp_project_files[cpp_current_file]
st.session_state.cpp_current_file = "main.cpp"
st.experimental_rerun()
else:
st.error("Cannot delete main.cpp")
with file_action_col2:
if st.button("Download Project Files", key="download_cpp_project"):
# Create a zip file with all project files
with tempfile.NamedTemporaryFile(delete=False, suffix=".zip") as tmp:
with zipfile.ZipFile(tmp.name, 'w') as zipf:
for filename, content in st.session_state.cpp_project_files.items():
# Add file to zip
zipf.writestr(filename, content)
# Download the zip file
with open(tmp.name, "rb") as f:
zip_data = f.read()
st.download_button(
label="Download ZIP",
data=zip_data,
file_name="cpp_project.zip",
mime="application/zip"
)
# Project structure visualization
st.markdown("### Project Structure")
# Group files by type
headers = []
sources = []
others = []
for filename in st.session_state.cpp_project_files:
if filename.endswith((".h", ".hpp")):
headers.append(filename)
elif filename.endswith((".cpp", ".c", ".cc")):
sources.append(filename)
else:
others.append(filename)
# Display structure
st.markdown("#### Header Files")
if headers:
for header in sorted(headers):
st.markdown(f"- `{header}`")
else:
st.markdown("No header files")
st.markdown("#### Source Files")
if sources:
for source in sorted(sources):
st.markdown(f"- `{source}`")
else:
st.markdown("No source files")
if others:
st.markdown("#### Other Files")
for other in sorted(others):
st.markdown(f"- `{other}`")
with cpp_tabs[2]: # Libraries tab
st.markdown("### Library Manager")
st.markdown("Configure libraries and dependencies for your C/C++ project")
# Common library selection
common_libs = st.multiselect(
"Common Libraries",
options=["Eigen", "Boost", "OpenCV", "FFTW", "SDL2", "SFML", "OpenGL", "stb_image", "nlohmann_json", "fmt"],
default=st.session_state.cpp_settings.get("libraries", []),
key="cpp_common_libs"
)
# Update libraries in settings
st.session_state.cpp_settings["libraries"] = common_libs
# Include paths
st.markdown("#### Include Paths")
include_paths = st.text_area(
"Include Directories (one per line)",
value="\n".join(st.session_state.cpp_settings.get("include_paths", [])),
height=100,
key="cpp_include_paths"
)
# Update include paths in settings
st.session_state.cpp_settings["include_paths"] = [path for path in include_paths.split("\n") if path.strip()]
# Library paths
st.markdown("#### Library Paths")
library_paths = st.text_area(
"Library Directories (one per line)",
value="\n".join(st.session_state.cpp_settings.get("library_paths", [])),
height=100,
key="cpp_library_paths"
)
# Update library paths in settings
st.session_state.cpp_settings["library_paths"] = [path for path in library_paths.split("\n") if path.strip()]
# Additional libraries
st.markdown("#### Additional Libraries")
additional_libs = st.text_area(
"Additional Libraries (one per line, without -l prefix)",
value="\n".join(st.session_state.cpp_settings.get("additional_libs", [])),
height=100,
key="cpp_additional_libs"
)
# Update additional libraries in settings
st.session_state.cpp_settings["additional_libs"] = [lib for lib in additional_libs.split("\n") if lib.strip()]
# Library detection
if st.button("Detect Installed Libraries", key="detect_libs"):
with st.spinner("Detecting libraries..."):
# This is a placeholder - in a real implementation, you'd scan the system
detected_libs = []
# Check for Eigen
try:
result = subprocess.run(
["find", "/usr/include", "-name", "Eigen"],
capture_output=True,
text=True,
timeout=5
)
if "Eigen" in result.stdout:
detected_libs.append("Eigen")
except:
pass
# Check for Boost
try:
result = subprocess.run(
["find", "/usr/include", "-name", "boost"],
capture_output=True,
text=True,
timeout=5
)
if "boost" in result.stdout:
detected_libs.append("Boost")
except:
pass
# Check for OpenCV
try:
result = subprocess.run(
["pkg-config", "--exists", "opencv4"],
capture_output=True,
timeout=5
)
if result.returncode == 0:
detected_libs.append("OpenCV")
except:
pass
# Display detected libraries
if detected_libs:
st.success(f"Detected libraries: {', '.join(detected_libs)}")
# Add to selected libraries if not already present
for lib in detected_libs:
if lib not in st.session_state.cpp_settings["libraries"]:
st.session_state.cpp_settings["libraries"].append(lib)
else:
st.warning("No common libraries detected")
with cpp_tabs[3]: # Build Settings tab
st.markdown("### Build Configuration")
# Build type
build_type = st.radio(
"Build Type",
options=["Debug", "Release", "RelWithDebInfo"],
index=1, # Default to Release
key="cpp_build_type"
)
# Update build type in settings
st.session_state.cpp_settings["build_type"] = build_type
# Advanced compiler flags
st.markdown("#### Advanced Compiler Flags")
advanced_flags = st.text_area(
"Additional Compiler Flags",
value=st.session_state.cpp_settings.get("advanced_flags", ""),
height=100,
key="cpp_advanced_flags"
)
# Update advanced flags in settings
st.session_state.cpp_settings["advanced_flags"] = advanced_flags
# Preprocessor definitions
st.markdown("#### Preprocessor Definitions")
definitions = st.text_area(
"Preprocessor Definitions (one per line)",
value="\n".join(st.session_state.cpp_settings.get("definitions", [])),
height=100,
placeholder="Example:\nDEBUG\nVERSION=1.0\nUSE_FEATURE_X",
key="cpp_definitions"
)
# Update definitions in settings
st.session_state.cpp_settings["definitions"] = [d for d in definitions.split("\n") if d.strip()]
# Generate CMakeLists.txt
if st.button("Generate CMakeLists.txt", key="gen_cmake"):
# Create CMakeLists.txt content
cmake_content = f"""cmake_minimum_required(VERSION 3.10)
project(ManimCppProject)
set(CMAKE_CXX_STANDARD {st.session_state.cpp_settings["std"].replace("c++", "")})
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
# Build type
set(CMAKE_BUILD_TYPE {build_type})
# Preprocessor definitions
"""
# Add definitions
for definition in st.session_state.cpp_settings.get("definitions", []):
if "=" in definition:
name, value = definition.split("=", 1)
cmake_content += f'add_definitions(-D{name}="{value}")\n'
else:
cmake_content += f"add_definitions(-D{definition})\n"
# Add include paths
if st.session_state.cpp_settings.get("include_paths", []):
cmake_content += "\n# Include directories\n"
for path in st.session_state.cpp_settings["include_paths"]:
cmake_content += f"include_directories({path})\n"
# Add library paths
if st.session_state.cpp_settings.get("library_paths", []):
cmake_content += "\n# Library directories\n"
for path in st.session_state.cpp_settings["library_paths"]:
cmake_content += f"link_directories({path})\n"
# Add common libraries
if "Eigen" in st.session_state.cpp_settings.get("libraries", []):
cmake_content += "\n# Eigen\n"
cmake_content += "find_package(Eigen3 REQUIRED)\n"
cmake_content += "include_directories(${EIGEN3_INCLUDE_DIR})\n"
if "OpenCV" in st.session_state.cpp_settings.get("libraries", []):
cmake_content += "\n# OpenCV\n"
cmake_content += "find_package(OpenCV REQUIRED)\n"
cmake_content += "include_directories(${OpenCV_INCLUDE_DIRS})\n"
if "Boost" in st.session_state.cpp_settings.get("libraries", []):
cmake_content += "\n# Boost\n"
cmake_content += "find_package(Boost REQUIRED)\n"
cmake_content += "include_directories(${Boost_INCLUDE_DIRS})\n"
# Add source files
cmake_content += "\n# Source files\n"
source_files = [f for f in st.session_state.cpp_project_files.keys() if f.endswith((".cpp", ".c", ".cc"))]
cmake_content += "add_executable(main\n"
for src in source_files:
cmake_content += f" {src}\n"
cmake_content += ")\n"
# Add libraries to link
cmake_content += "\n# Link libraries\n"
cmake_content += "target_link_libraries(main\n"
if "OpenCV" in st.session_state.cpp_settings.get("libraries", []):
cmake_content += " ${OpenCV_LIBS}\n"
if "Boost" in st.session_state.cpp_settings.get("libraries", []):
cmake_content += " ${Boost_LIBRARIES}\n"
# Additional libraries
for lib in st.session_state.cpp_settings.get("additional_libs", []):
cmake_content += f" {lib}\n"
cmake_content += ")\n"
# Save CMakeLists.txt to project files
st.session_state.cpp_project_files["CMakeLists.txt"] = cmake_content
# Show the generated file
st.success("CMakeLists.txt generated!")
st.code(cmake_content, language="cmake")
with cpp_tabs[4]: # Debugger tab
st.markdown("### C++ Debugger")
st.markdown("Debug your C++ code with breakpoints and variable inspection")
# Enable debugging
enable_cpp_debug = st.checkbox("Enable Debugging", value=False, key="cpp_debug_enable")
if enable_cpp_debug:
# Breakpoints
st.markdown("#### Breakpoints")
st.markdown("Enter line numbers for breakpoints (one per line)")
breakpoints = st.text_area(
"Breakpoints",
placeholder="Example:\n10\n15\n20",
height=100,
key="cpp_breakpoints"
)
breakpoint_lines = []
for line in breakpoints.split("\n"):
try:
line_num = int(line.strip())
if line_num > 0:
breakpoint_lines.append(line_num)
except:
pass
# Watch variables
st.markdown("#### Watch Variables")
st.markdown("Enter variable names to watch (one per line)")
watch_vars = st.text_area(
"Watch Variables",
placeholder="Example:\ni\nsum\nresult",
height=100,
key="cpp_watch_vars"
)
watch_variables = [var.strip() for var in watch_vars.split("\n") if var.strip()]
# Compilation and execution options
st.markdown("### Run Configuration")
run_options_col1, run_options_col2 = st.columns(2)
with run_options_col1:
cpp_timeout = st.slider("Execution Timeout (seconds)", 1, 60, 10)
with run_options_col2:
compile_btn = st.button("đ ī¸ Compile and Run", use_container_width=True)
# Compile and run the C++ code
if compile_btn:
with st.spinner("Compiling C++ code..."):
cpp_code_to_compile = st.session_state.cpp_code
if "cpp_project_files" in st.session_state and st.session_state.cpp_project_files:
# Use project files
executable_path, compile_error, temp_dir = compile_cpp_code_enhanced(
cpp_code_to_compile,
st.session_state.cpp_settings,
project_files=st.session_state.cpp_project_files,
enable_debug=enable_cpp_debug if "enable_cpp_debug" in locals() else False,
breakpoints=breakpoint_lines if "breakpoint_lines" in locals() else None,
watch_vars=watch_variables if "watch_variables" in locals() else None
)
else:
# Use single file
executable_path, compile_error, temp_dir = compile_cpp_code_enhanced(
cpp_code_to_compile,
st.session_state.cpp_settings,
enable_debug=enable_cpp_debug if "enable_cpp_debug" in locals() else False,
breakpoints=breakpoint_lines if "breakpoint_lines" in locals() else None,
watch_vars=watch_variables if "watch_variables" in locals() else None
)
if compile_error:
st.error("Compilation Error:")
st.code(compile_error, language="bash")
else:
st.success("Compilation successful!")
with st.spinner("Running program..."):
result = run_cpp_executable_enhanced(
executable_path,
temp_dir,
inputs=cpp_inputs if "cpp_inputs" in locals() else None,
timeout=cpp_timeout,
enable_debug=enable_cpp_debug if "enable_cpp_debug" in locals() else False,
breakpoints=breakpoint_lines if "breakpoint_lines" in locals() else None,
watch_vars=watch_variables if "watch_variables" in locals() else None
)
st.session_state.cpp_result = result
# Display results
if "cpp_result" in st.session_state and st.session_state.cpp_result:
result = st.session_state.cpp_result
st.markdown("### Results")
# Execution information
info_cols = st.columns(3)
with info_cols[0]:
st.info(f"Execution Time: {result['execution_time']:.3f} seconds")
with info_cols[1]:
if result.get("memory_usage"):
st.info(f"Memory Usage: {result['memory_usage']:.2f} MB")
with info_cols[2]:
if result["exception"]:
st.error(f"Exception: {result['exception']}")
# Show debug output if available
if result.get("debug_output"):
with st.expander("Debug Output", expanded=True):
st.code(result["debug_output"], language="bash")
# Result tabs
result_tabs = st.tabs(["Output", "Images", "Manim Integration"])
with result_tabs[0]: # Output tab
# Show stdout if any
if result["stdout"]:
st.markdown("#### Standard Output")
st.code(result["stdout"], language="bash")
# Show stderr if any
if result["stderr"]:
st.markdown("#### Standard Error")
st.code(result["stderr"], language="bash")
with result_tabs[1]: # Images tab
# Show images if any
if result["images"]:
st.markdown("#### Generated Images")
img_cols = st.columns(min(3, len(result["images"])))
for i, img in enumerate(result["images"]):
with img_cols[i % len(img_cols)]:
st.image(img["data"], caption=img["name"])
else:
st.info("No images were generated by the program.")
with result_tabs[2]: # Manim Integration tab
st.markdown("#### Integrate C++ Results with Manim")
# Create options for integration
integration_type = st.radio(
"Integration Type",
options=["Data Visualization", "Image Import", "Animation Sequence"],
key="cpp_integration_type"
)
if integration_type == "Data Visualization":
# Extract numerical data from stdout if possible
lines = result["stdout"].strip().split("\n")
data_options = []
for i, line in enumerate(lines):
# Check if line contains numbers
numbers = []
try:
# Try to extract numbers from the line
numbers = [float(x) for x in line.split() if x.replace(".", "").isdigit()]
if numbers:
data_options.append(f"Line {i+1}: {line[:30]}{'...' if len(line) > 30 else ''}")
except:
pass
if data_options:
selected_data_line = st.selectbox(
"Select Data to Visualize",
options=["Select a line..."] + data_options,
key="cpp_data_line"
)
if selected_data_line != "Select a line...":
line_idx = int(selected_data_line.split(":")[0].replace("Line ", "")) - 1
line = lines[line_idx]
# Extract numbers
try:
numbers = [float(x) for x in line.split() if x.replace(".", "").isdigit()]
# Preview the data
st.markdown(f"**Extracted Data:** {numbers}")
# Create visualization code
if st.button("Create Manim Visualization", key="cpp_create_viz"):
viz_code = f"""
# Visualize data from C++ output
values = {numbers}
axes = Axes(
x_range=[0, {len(numbers)}, 1],
y_range=[{min(numbers) if numbers else 0}, {max(numbers) if numbers else 10}, {(max(numbers)-min(numbers))/10 if numbers and max(numbers) > min(numbers) else 1}],
axis_config={{"color": BLUE}}
)
points = [axes.coords_to_point(i, v) for i, v in enumerate(values)]
dots = VGroup(*[Dot(point, color=RED) for point in points])
graph = VMobject(color=YELLOW)
graph.set_points_as_corners(points)
self.play(Create(axes))
self.play(Create(dots), run_time=2)
self.play(Create(graph), run_time=2)
self.wait(1)
"""
if st.session_state.code:
st.session_state.code += "\n" + viz_code
else:
st.session_state.code = f"""from manim import *
class CppDataVisualizationScene(Scene):
def construct(self):
{viz_code}
"""
st.session_state.temp_code = st.session_state.code
st.success("Added C++ data visualization to your Manim code!")
# Set pending tab switch to editor tab
st.session_state.pending_tab_switch = 0
st.rerun()
except Exception as e:
st.error(f"Error extracting numbers: {str(e)}")
else:
st.warning("No numeric data detected in the output.")
elif integration_type == "Image Import":
# Handle image import
if result["images"]:
st.markdown("#### Select Images to Import")
for i, img in enumerate(result["images"]):
st.markdown(f"**{img['name']}**")
st.image(img["data"], width=300)
if st.button(f"Use in Manim", key=f"use_cpp_img_{i}"):
# Save image to a temporary file
with tempfile.NamedTemporaryFile(delete=False, suffix=f"_{img['name']}") as tmp:
tmp.write(img["data"])
img_path = tmp.name
# Generate Manim code
image_code = f"""
# Load and display image generated from C++
cpp_image = ImageMobject(r"{img_path}")
cpp_image.scale(2) # Adjust size as needed
self.play(FadeIn(cpp_image))
self.wait(1)
"""
if st.session_state.code:
st.session_state.code += "\n" + image_code
else:
st.session_state.code = f"""from manim import *
class CppImageScene(Scene):
def construct(self):
{image_code}
"""
st.session_state.temp_code = st.session_state.code
st.success(f"Added C++ generated image to your Manim code!")
st.session_state.pending_tab_switch = 0 # Switch to editor tab
st.rerun()
else:
st.warning("No images were generated by the C++ program.")
elif integration_type == "Animation Sequence":
st.markdown("#### Create Animation Sequence")
st.info("This will create a Manim animation that visualizes the execution of your C++ program.")
# Animation type options
animation_style = st.selectbox(
"Animation Style",
options=["Algorithm Visualization", "Data Flow", "Memory Model"],
key="cpp_anim_style"
)
if st.button("Generate Animation Sequence", key="cpp_gen_anim_seq"):
# Create different animations based on selected style
if animation_style == "Algorithm Visualization":
# Example code for algorithm visualization
algo_code = f"""
# C++ Algorithm Visualization
title = Text("C++ Algorithm Visualization")
self.play(Write(title))
self.play(title.animate.to_edge(UP))
self.wait(0.5)
# Create an array representation
values = [5, 2, 8, 1, 9, 3, 7, 4, 6] # Example values
squares = VGroup(*[Square(side_length=0.7, fill_opacity=0.8, fill_color=BLUE) for _ in values])
squares.arrange(RIGHT, buff=0.1)
labels = VGroup(*[Text(str(v), font_size=24) for v in values])
for label, square in zip(labels, squares):
label.move_to(square.get_center())
array = VGroup(squares, labels)
array_label = Text("Array", font_size=20).next_to(array, UP)
self.play(FadeIn(array), Write(array_label))
self.wait(1)
# Simulate sorting algorithm
for i in range(len(values)-1):
# Highlight current element
self.play(squares[i].animate.set_fill(RED))
for j in range(i+1, len(values)):
# Highlight comparison element
self.play(squares[j].animate.set_fill(YELLOW))
# Simulate comparison
if values[i] > values[j]:
# Swap animation
self.play(
labels[i].animate.move_to(squares[j].get_center()),
labels[j].animate.move_to(squares[i].get_center())
)
# Update values and labels
labels[i], labels[j] = labels[j], labels[i]
values[i], values[j] = values[j], values[i]
# Reset comparison element
self.play(squares[j].animate.set_fill(BLUE))
# Mark current element as processed
self.play(squares[i].animate.set_fill(GREEN))
# Mark the last element as processed
self.play(squares[-1].animate.set_fill(GREEN))
# Show sorted array
sorted_label = Text("Sorted Array", font_size=20).next_to(array, DOWN)
self.play(Write(sorted_label))
self.wait(2)
"""
if st.session_state.code:
st.session_state.code += "\n" + algo_code
else:
st.session_state.code = f"""from manim import *
class CppAlgorithmScene(Scene):
def construct(self):
{algo_code}
"""
st.session_state.temp_code = st.session_state.code
st.success("Added C++ algorithm visualization to your Manim code!")
st.session_state.pending_tab_switch = 0 # Switch to editor tab
st.rerun()
elif animation_style == "Data Flow":
# Example code for data flow visualization
data_flow_code = f"""
# C++ Data Flow Visualization
title = Text("C++ Data Flow")
self.play(Write(title))
self.play(title.animate.to_edge(UP))
self.wait(0.5)
# Create nodes for data flow
input_node = Circle(radius=0.5, fill_opacity=0.8, fill_color=BLUE)
process_node = Square(side_length=1, fill_opacity=0.8, fill_color=GREEN)
output_node = Circle(radius=0.5, fill_opacity=0.8, fill_color=RED)
# Position nodes
input_node.move_to(LEFT*4)
process_node.move_to(ORIGIN)
output_node.move_to(RIGHT*4)
# Add labels
input_label = Text("Input", font_size=20).next_to(input_node, DOWN)
process_label = Text("Process", font_size=20).next_to(process_node, DOWN)
output_label = Text("Output", font_size=20).next_to(output_node, DOWN)
# Create arrows
arrow1 = Arrow(input_node.get_right(), process_node.get_left(), buff=0.2)
arrow2 = Arrow(process_node.get_right(), output_node.get_left(), buff=0.2)
# Display nodes and arrows
self.play(FadeIn(input_node), Write(input_label))
self.wait(0.5)
self.play(FadeIn(process_node), Write(process_label))
self.wait(0.5)
self.play(FadeIn(output_node), Write(output_label))
self.wait(0.5)
self.play(Create(arrow1), Create(arrow2))
self.wait(1)
# Simulate data flow
data = Text("Data", font_size=16).move_to(input_node.get_center())
self.play(FadeIn(data))
self.wait(0.5)
# Move data along the flow
self.play(data.animate.move_to(arrow1.get_center()))
self.wait(0.5)
self.play(data.animate.move_to(process_node.get_center()))
self.wait(0.5)
transformed_data = Text("Processed", font_size=16, color=YELLOW)
transformed_data.move_to(process_node.get_center())
self.play(Transform(data, transformed_data))
self.wait(0.5)
self.play(data.animate.move_to(arrow2.get_center()))
self.wait(0.5)
self.play(data.animate.move_to(output_node.get_center()))
self.wait(1)
result_text = Text("Final Result", font_size=24).to_edge(DOWN)
self.play(Write(result_text))
self.wait(2)
"""
if st.session_state.code:
st.session_state.code += "\n" + data_flow_code
else:
st.session_state.code = f"""from manim import *
class CppDataFlowScene(Scene):
def construct(self):
{data_flow_code}
"""
st.session_state.temp_code = st.session_state.code
st.success("Added C++ data flow visualization to your Manim code!")
st.session_state.pending_tab_switch = 0 # Switch to editor tab
st.rerun()
elif animation_style == "Memory Model":
# Example code for memory model visualization
memory_code = f"""
# C++ Memory Model Visualization
title = Text("C++ Memory Model")
self.play(Write(title))
self.play(title.animate.to_edge(UP))
self.wait(0.5)
# Create memory blocks
stack_rect = Rectangle(height=3, width=4, fill_opacity=0.2, fill_color=BLUE)
stack_rect.move_to(LEFT*3.5)
stack_label = Text("Stack", font_size=20).next_to(stack_rect, UP)
heap_rect = Rectangle(height=3, width=4, fill_opacity=0.2, fill_color=RED)
heap_rect.move_to(RIGHT*3.5)
heap_label = Text("Heap", font_size=20).next_to(heap_rect, UP)
# Display memory areas
self.play(
Create(stack_rect), Write(stack_label),
Create(heap_rect), Write(heap_label)
)
self.wait(1)
# Create variables on the stack
int_var = Rectangle(height=0.5, width=1.5, fill_opacity=0.8, fill_color=BLUE_C)
int_var.move_to(stack_rect.get_center() + UP*1)
int_label = Text("int x = 5", font_size=16).next_to(int_var, RIGHT)
pointer_var = Rectangle(height=0.5, width=1.5, fill_opacity=0.8, fill_color=BLUE_D)
pointer_var.move_to(stack_rect.get_center())
pointer_label = Text("int* ptr", font_size=16).next_to(pointer_var, RIGHT)
# Display stack variables
self.play(FadeIn(int_var), Write(int_label))
self.wait(0.5)
self.play(FadeIn(pointer_var), Write(pointer_label))
self.wait(1)
# Create heap allocation
heap_alloc = Rectangle(height=0.8, width=2, fill_opacity=0.8, fill_color=RED_C)
heap_alloc.move_to(heap_rect.get_center() + UP*0.5)
heap_label = Text("new int[4]", font_size=16).next_to(heap_alloc, LEFT)
# Display heap allocation
self.play(FadeIn(heap_alloc), Write(heap_label))
self.wait(1)
# Create arrow from pointer to heap
arrow = Arrow(pointer_var.get_right(), heap_alloc.get_left(), buff=0.2, color=YELLOW)
self.play(Create(arrow))
self.wait(0.5)
# Simulate pointer assignment
assign_text = Text("ptr = new int[4]", font_size=24).to_edge(DOWN)
self.play(Write(assign_text))
self.wait(1)
# Simulate memory deallocation
delete_text = Text("delete[] ptr", font_size=24).to_edge(DOWN)
self.play(Transform(assign_text, delete_text))
self.play(FadeOut(arrow), FadeOut(heap_alloc), FadeOut(heap_label))
self.wait(1)
# Simulate end of scope
end_scope = Text("End of scope", font_size=24).to_edge(DOWN)
self.play(Transform(assign_text, end_scope))
self.play(FadeOut(int_var), FadeOut(int_label), FadeOut(pointer_var), FadeOut(pointer_label))
self.wait(2)
"""
if st.session_state.code:
st.session_state.code += "\n" + memory_code
else:
st.session_state.code = f"""from manim import *
class CppMemoryModelScene(Scene):
def construct(self):
{memory_code}
"""
st.session_state.temp_code = st.session_state.code
st.success("Added C++ memory model visualization to your Manim code!")
st.session_state.pending_tab_switch = 0 # Switch to editor tab
st.rerun()
# C++ Information and tips
with st.expander("C/C++ Runner Information"):
st.markdown("""
### C/C++ Runner Tips
**Compilation Options:**
- Choose the appropriate compiler based on your platform
- Select the C++ standard version for your code
- Optimization levels affect performance and debugging
**Library Support:**
- Common libraries like Eigen, OpenCV, and Boost are supported
- Add custom include paths and library paths as needed
- Use the library detection feature to find installed libraries
**Input/Output:**
- Standard input/output (cin/cout) is fully supported
- File I/O works within the execution directory
- For interactive programs, provide input values in advance
**Debugging:**
- Set breakpoints at specific line numbers
- Watch variables to track their values
- Debug with GDB for detailed analysis
**Project Management:**
- Create multi-file projects with headers and source files
- Generate CMakeLists.txt for complex projects
- Download project files as a ZIP archive
**Images and Visualization:**
- Generate images in PPM, PNG, JPG formats
- Use OpenCV for more advanced image processing
- All generated images can be used in Manim animations
**Manim Integration:**
- Create algorithm visualizations from C++ code
- Import C++ generated images into Manim scenes
- Visualize data structures and memory models
**Performance:**
- Use release mode for best performance
- Profile your code to identify bottlenecks
- C++ is ideal for computationally intensive tasks
""")
# Help section
with st.sidebar.expander("âšī¸ Help & Info"):
st.markdown("""
### About Manim Animation Studio
This app allows you to create mathematical animations using Manim,
an animation engine for explanatory math videos.
### Example Code
```python
from manim import *
class SimpleExample(Scene):
def construct(self):
circle = Circle(color=BLUE)
self.play(Create(circle))
square = Square(color=RED).next_to(circle, RIGHT)
self.play(Create(square))
text = Text("Manim Animation").next_to(VGroup(circle, square), DOWN)
self.play(Write(text))
self.wait(2)
```
""")
# Handle tab switching with session state to prevent refresh loop
if st.session_state.pending_tab_switch is not None:
st.session_state.active_tab = st.session_state.pending_tab_switch
st.session_state.pending_tab_switch = None
# Set tabs active state
for i, tab in enumerate(tabs):
if i == st.session_state.active_tab:
tab.active = True
# Mark first load as complete to prevent unnecessary refreshes
if not st.session_state.first_load_complete:
st.session_state.first_load_complete = True
if __name__ == "__main__":
main()