summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@gmail.com>2011-11-03 23:39:07 -0400
committerTavian Barnes <tavianator@gmail.com>2011-11-04 18:10:10 -0400
commitdc281b3471773935ec4da66864e6a6c768c41ff6 (patch)
treebd7003df0f2571f3a53c22dc8638209e7970a3f1
parente8bdfce85fbf792eaf8be47c6ecff01f99c94ee6 (diff)
downloaddimension-dc281b3471773935ec4da66864e6a6c768c41ff6.tar.xz
Add a preview window written with PyQt.
-rw-r--r--Makefile.am4
-rw-r--r--dimension/Makefile.am3
-rw-r--r--dimension/client.py.in26
-rw-r--r--dimension/preview.py66
4 files changed, 96 insertions, 3 deletions
diff --git a/Makefile.am b/Makefile.am
index f455fe3..6cad2e3 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -28,9 +28,11 @@ EXTRA_DIST = autogen.sh
# Set up ./dimension as a python package for tests
$(abs_builddir)/dimension/__init__.py:
ln -sf "$(abs_top_srcdir)/dimension/__init__.py" dimension/__init__.py
+$(abs_builddir)/dimension/preview.py:
+ ln -sf "$(abs_top_srcdir)/dimension/preview.py" dimension/preview.py
$(abs_builddir)/dimension/wrapper.so:
ln -sf ../libdimension-python/.libs/wrapper.so dimension/wrapper.so
-all-local: $(abs_builddir)/dimension/__init__.py $(abs_builddir)/dimension/wrapper.so
+all-local: $(abs_builddir)/dimension/__init__.py $(abs_builddir)/dimension/preview.py $(abs_builddir)/dimension/wrapper.so
bench:
cd libdimension && $(MAKE) $(AM_MAKEFLAGS) bench
diff --git a/dimension/Makefile.am b/dimension/Makefile.am
index c12a6b7..a892601 100644
--- a/dimension/Makefile.am
+++ b/dimension/Makefile.am
@@ -26,7 +26,8 @@ dist_bin_SCRIPTS = dimension
# since it's not really installed, so disable the --help and --version checks
AM_INSTALLCHECK_STD_OPTIONS_EXEMPT = dimension
-pkgpython_PYTHON = __init__.py
+pkgpython_PYTHON = __init__.py \
+ preview.py
nodist_pkgpython_PYTHON = client.py
clean-local:
diff --git a/dimension/client.py.in b/dimension/client.py.in
index 4881f62..127b96c 100644
--- a/dimension/client.py.in
+++ b/dimension/client.py.in
@@ -23,9 +23,16 @@ import argparse
import re
import os
import sys
+import threading
from contextlib import contextmanager
from dimension import *
+have_preview = True
+try:
+ from dimension import preview
+except ImportError:
+ have_preview = False
+
def main():
"""Invoke the client from the command line."""
@@ -68,6 +75,9 @@ def main():
parser.add_argument("input", action = "store", type = str,
help = "the input scene description file")
+ parser.add_argument("-p", "--preview", action = "store_true",
+ help = "display a preview while the image renders")
+
# Debugging/testing options
parser.add_argument("--strict", action = "store_true",
help = argparse.SUPPRESS)
@@ -118,6 +128,8 @@ def main():
# Make the canvas
canvas = Canvas(width = args.region_width, height = args.region_height)
canvas.optimize_PNG()
+ if args.preview:
+ canvas.optimize_GL()
# Make the scene object
scene = Scene(canvas = canvas,
@@ -146,12 +158,19 @@ def main():
# Ray-trace the scene
future = scene.ray_trace_async()
+ bar = None
if not args.quiet:
if scene.nthreads == 1:
render_message = "Rendering scene"
else:
render_message = "Rendering scene (using %d threads)" % scene.nthreads
- progress_bar(render_message, future)
+ bar = progress_bar_async(render_message, future)
+ if args.preview:
+ if have_preview:
+ preview.show_preview(canvas, future)
+ else:
+ print("Couldn't display preview window", file = sys.stderr)
+ bar.join()
future.join()
# Write the output file
@@ -238,3 +257,8 @@ def progress_bar(str, future):
# Swallow the failure exception
pass
raise
+
+def progress_bar_async(str, future):
+ thread = threading.Thread(target = progress_bar, args = (str, future))
+ thread.start()
+ return thread
diff --git a/dimension/preview.py b/dimension/preview.py
new file mode 100644
index 0000000..868c16b
--- /dev/null
+++ b/dimension/preview.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python3
+
+#########################################################################
+# Copyright (C) 2011 Tavian Barnes <tavianator@tavianator.com> #
+# #
+# This file is part of Dimension. #
+# #
+# Dimension is free software; you can redistribute it and/or modify it #
+# under the terms of the GNU General Public License as published by the #
+# Free Software Foundation; either version 3 of the License, or (at #
+# your option) any later version. #
+# #
+# Dimension is distributed in the hope that it will be useful, but #
+# WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU #
+# General Public License for more details. #
+# #
+# You should have received a copy of the GNU General Public License #
+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
+#########################################################################
+
+from PyQt4 import QtCore, QtGui, QtOpenGL
+
+class Preview(QtOpenGL.QGLWidget):
+ """Surface that the scene is rendered to."""
+ def __init__(self, parent, canvas):
+ QtOpenGL.QGLWidget.__init__(self, parent)
+ self.canvas = canvas
+
+ def paintGL(self):
+ self.canvas.draw_GL()
+
+class PreviewWindow(QtGui.QMainWindow):
+ """Main window for a rendering preview."""
+ def __init__(self, canvas, future):
+ QtGui.QMainWindow.__init__(self)
+ self.canvas = canvas
+ self.future = future
+
+ self.setMinimumSize(canvas.width, canvas.height)
+ self.setMaximumSize(canvas.width, canvas.height)
+ self.widget = Preview(self, canvas)
+ self.setCentralWidget(self.widget)
+
+ self.render_timer = QtCore.QTimer(self)
+ self.render_timer.timeout.connect(self.update_preview)
+ self.render_timer.start(0)
+
+ @QtCore.pyqtSlot()
+ def update_preview(self):
+ self.widget.updateGL()
+ if self.future.progress() == 1:
+ self.render_timer.stop()
+ self.close_timer = QtCore.QTimer(self)
+ self.close_timer.singleShot(1000, self.close)
+
+ @QtCore.pyqtSlot()
+ def close(self):
+ QtCore.QCoreApplication.instance().quit()
+
+def show_preview(canvas, future):
+ app = QtGui.QApplication(["Dimension Preview"])
+ window = PreviewWindow(canvas, future)
+ window.show()
+ app.exec()
+ del window