import gradio as gr
import json
from devcore.parser import parse_description
from devcore.builder import description_to_blueprint, blueprint_to_json
EXAMPLE_PROMPTS = [
"2000 sq ft ranch house with 3 bedrooms and 2 baths",
"modern 2-story house 30x40 with 4 bedrooms 3 bathrooms and a garage",
"small cabin 800 sq ft with 1 bedroom and a loft",
"victorian 3500 sq ft 5 bedroom 3 bath with office and library",
"colonial with 4 bedrooms and 2.5 baths",
"my house is 50 feet wide and 60 feet long with 3 bedrooms",
"30 feet by 50 feet modern house with 4 bedrooms and a deck",
]
def build_blueprint(description):
if not description or not description.strip():
html = _render_empty("Enter a description of the building you want to visualize.")
return html, "No description provided.", "", ""
try:
html = description_to_blueprint(description)
data = parse_description(description)
s = data["structure"]
f = data["features"]
summary = data["summary"]
details = (
f"๐ **{s['style'].title()}** ยท {f['stories']} story ยท "
f"{s['width']}ft ร {s['depth']}ft ยท ~{s['sqft']} sqft\n"
f"๐๏ธ {f['bedrooms']} bed ยท ๐ฟ {f['bathrooms']} bath ยท "
f"{'๐ Garage' if f['garage'] else 'No garage'}"
)
roof = s.get("roof_style", "gable")
extras = f"๐๏ธ {roof} roof ยท ๐ฑ๏ธ Orbit/Pan/Tour modes ยท ๐ฅ Export JSON"
return html, summary, details, extras
except Exception as e:
html = _render_empty(f"Error: {e}")
return html, f"Failed to build: {e}", "", ""
def _render_empty(message):
return f"""
๐๏ธ 3D Blueprint Builder
{message}
Type a description above and click Build
"""
with gr.Blocks(title="Vitalis DevCore โ 3D Blueprint Builder", theme=gr.themes.Soft(primary_hue="purple", secondary_hue="indigo")) as demo:
gr.HTML("""
Vitalis DevCore โ 3D Blueprint Builder
Describe a building in natural language โ see it rendered as an interactive 3D model
""")
with gr.Row():
with gr.Column(scale=3):
prompt = gr.Textbox(
label="Describe your building",
placeholder="e.g., 2000 sq ft ranch house with 3 bedrooms and 2 baths",
lines=2,
)
with gr.Column(scale=1):
build_btn = gr.Button("๐๏ธ Build Blueprint", variant="primary", size="lg", scale=1)
with gr.Row():
summary_display = gr.Markdown(label="Summary", value="Enter a description and click Build.")
with gr.Row():
with gr.Column(scale=2):
model_display = gr.HTML(label="3D Model")
with gr.Accordion("Example prompts", open=True):
example_btns = []
for ex in EXAMPLE_PROMPTS:
btn = gr.Button(ex, size="sm")
btn.click(fn=lambda e=ex: e, outputs=prompt)
example_btns.append(btn)
with gr.Accordion("Blueprint Details", open=False):
details_display = gr.Markdown(label="Details")
extras_display = gr.Markdown(label="Features")
def on_build(desc):
html, summary, details, extras = build_blueprint(desc)
return html, summary, details, extras
build_btn.click(
fn=on_build,
inputs=[prompt],
outputs=[model_display, summary_display, details_display, extras_display],
)
prompt.submit(
fn=on_build,
inputs=[prompt],
outputs=[model_display, summary_display, details_display, extras_display],
)
gr.Markdown("---")
with gr.Row():
gr.Markdown("""
### View Controls
- **Orbit** โ Drag to rotate, scroll to zoom
- **Pan** โ Drag to move view
- **Tour** โ Auto- camera walkthrough of rooms
- **Export** โ Download blueprint as JSON
*Style-specific roofs: gable, hip, flat, steep-gable ยท Measurements shown on each room ยท All rendering in-browser*
""")
with gr.Accordion("JSON Blueprint Data (read-only)", open=False):
json_display = gr.Markdown("Build a blueprint first.")
def show_json(desc):
if not desc or not desc.strip():
return "Enter a description."
try:
return "```json\n" + blueprint_to_json(desc) + "\n```"
except:
return "Invalid description."
prompt.change(show_json, inputs=[prompt], outputs=json_display)
gr.Markdown("*Vitalis DevCore โ Natural Language โ 3D Blueprint ยท Built with Three.js*")
if __name__ == "__main__":
demo.launch()