diff --git a/release/scripts/op/image.py b/release/scripts/op/image.py index e0e75a1f17a..bb178a4ba4e 100644 --- a/release/scripts/op/image.py +++ b/release/scripts/op/image.py @@ -181,13 +181,320 @@ class ProjectApply(bpy.types.Operator): return {'FINISHED'} +#!/usr/bin/env python +# stripped down code from youtube-dl: +# http://bitbucket.org/rg3/youtube-dl/wiki/Home +# License: Public domain code + +import os +import os.path +import random +import re +import socket +import string +import tempfile +import time +import urllib +import urllib.request +import getpass + +std_headers = { + 'User-Agent': 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6', + 'Accept-Charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.7', + 'Accept': 'text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5', + 'Accept-Language': 'en-us,en;q=0.5', +} + +class DownloadError(Exception): + pass + +class FileDownloader(object): + params = None + _ies = [] + _download_retcode = None + + def __init__(self, params): + self._ies = [] + self._download_retcode = 0 + self.params = params + + @staticmethod + def calc_percent(byte_counter, data_len): + if data_len is None: + return '---.-%' + return '%6s' % ('%3.1f%%' % (float(byte_counter) / float(data_len) * 100.0)) + + @staticmethod + def best_block_size(elapsed_time, bytes): + new_min = max(bytes / 2.0, 1.0) + new_max = min(max(bytes * 2.0, 1.0), 4194304) # Do not surpass 4 MB + if elapsed_time < 0.001: + return int(new_max) + rate = bytes / elapsed_time + if rate > new_max: + return int(new_max) + if rate < new_min: + return int(new_min) + return int(rate) + + @staticmethod + def verify_url(url): + request = urllib.request.Request(url, None, std_headers) + data = urllib.request.urlopen(request) + data.read(1) + url = data.geturl() + data.close() + return url + + def to_stdout(self, message, skip_eol=False, ignore_encoding_errors=False): + print(message) + + def to_stderr(self, message): + print(message) + + def trouble(self, message=None): + if message is not None: + self.to_stderr(message) + raise DownloadError(message) + self._download_retcode = 1 + + def report_progress(self, percent_str): + print(percent_str) + + def process_info(self, url, filename): + success = self._do_download(filename, url) + + def download(self, url, filename): + ie = YoutubeSearchIE(YoutubeIE(self)) + ie.extract(url, filename) + + return self._download_retcode + + def _do_download(self, filename, url): + stream = None + open_mode = 'wb' + request = urllib.request.Request(url, None, std_headers) + + # Establish connection + try: + data = urllib.request.urlopen(request) + except: + raise + + limit = 1024*256 # quarter of a megabyte max + + data_len = float(data.info().get('Content-length', None)) + byte_counter = 0 + block_size = 1024 + start = time.time() + while True: + # Download and write + before = time.time() + data_block = data.read(block_size) + after = time.time() + data_block_len = len(data_block) + if data_block_len == 0: + break + byte_counter += data_block_len + + # Open file just in time + if stream is None: + try: + stream = open(filename, open_mode) + except: + return False + stream.write(data_block) + block_size = self.best_block_size(after - before, data_block_len) + + # Progress message + percent_str = self.calc_percent(byte_counter, min(data_len, limit)) + self.report_progress(percent_str) + + if byte_counter > limit: + break + + return True + +class InfoExtractor(object): + _ready = False + _downloader = None + + def __init__(self, downloader=None): + self._ready = False + self._downloader = downloader + + def initialize(self): + if not self._ready: + self._real_initialize() + self._ready = True + + def extract(self, url, filename): + self.initialize() + return self._real_extract(url, filename) + +class YoutubeIE(InfoExtractor): + _VALID_URL = r'^((?:http://)?(?:\w+\.)?youtube\.com/(?:(?:v/)|(?:(?:watch(?:\.php)?)?[\?#](?:.+&)?v=)))?([0-9A-Za-z_-]+)(?(1).+)?$' + _LANG_URL = r'http://uk.youtube.com/?hl=en&persist_hl=1&gl=US&persist_gl=1&opt_out_ackd=1' + + def _real_initialize(self): + if self._downloader is None: + return + + # Set language + request = urllib.request.Request(self._LANG_URL, None, std_headers) + try: + urllib.request.urlopen(request).read() + except: + print("unable to set language") + return + + def _real_extract(self, url, filename): + # Extract video id from URL + video_id = re.match(self._VALID_URL, url).group(2) + + # Get video info + video_info_url = 'http://www.youtube.com/get_video_info?&video_id=%s&el=detailpage&ps=default&eurl=&gl=US&hl=en' % video_id + request = urllib.request.Request(video_info_url, None, std_headers) + try: + video_info_webpage = urllib.request.urlopen(request).read() + video_info = urllib.parse.parse_qs(str(video_info_webpage)) + except: + print("unable to download info") + return + + # "t" param + if 'token' not in video_info: + return + token = urllib.parse.unquote_plus(video_info['token'][0]) + video_real_url = 'http://www.youtube.com/get_video?video_id=%s&t=%s&eurl=&el=detailpage&ps=default&gl=US&hl=en' % (video_id, token) + + # Process video information + self._downloader.process_info(video_real_url, filename) + +class YoutubeSearchIE(InfoExtractor): + _TEMPLATE_URL = 'http://www.youtube.com/results?search_query=%s&page=%s&gl=US&hl=en' + _VIDEO_INDICATOR = r'href="/watch\?v=.+?"' + _youtube_ie = None + + def __init__(self, youtube_ie, downloader=None): + InfoExtractor.__init__(self, downloader) + self._youtube_ie = youtube_ie + + def _real_initialize(self): + self._youtube_ie.initialize() + + def _real_extract(self, query, filename): + n = 1 + + result_url = self._TEMPLATE_URL % (urllib.parse.quote_plus(query), 1) + request = urllib.request.Request(result_url, None, std_headers) + try: + page = str(urllib.request.urlopen(request).read()) + except: + print("unable to download search page") + return + + # Extract video identifiers + for mobj in re.finditer(self._VIDEO_INDICATOR, page): + video_id = page[mobj.span()[0]:mobj.span()[1]].split('=')[2][:-1] + self._youtube_ie.extract('http://www.youtube.com/watch?v=%s' % video_id, filename) + return + +### MAIN PROGRAM ### +def download_movie(search_terms, filename): + try: + urllib.request.install_opener(urllib.request.build_opener(urllib.request.ProxyHandler())) + urllib.request.install_opener(urllib.request.build_opener(urllib.request.HTTPCookieProcessor())) + socket.setdefaulttimeout(10) + + fd = FileDownloader({}) + fd.download(search_terms, filename) + return 1 + except DownloadError: + return 0 + +import bpy + +class MakeAMovie(bpy.types.Operator): + '''Make a movie button''' + bl_idname = "render.make_a_movie" + bl_label = "Make A Movie Button" + bl_options = {'REGISTER', 'UNDO'} + + def invoke(self, context, event): + context.scene.thinking = "thinking .. this may take a while" + context.manager.add_modal_handler(self) + return {'RUNNING_MODAL'} + + def modal(self, context, event): + try: + bpy.ops.render.view_cancel() + except: + pass + + try: + about = context.scene.about + filename = os.path.join(tempfile.gettempdir(), "make_a_movie.flv") + if not download_movie(about, filename): + context.scene.thinking = "make a movie button is out of inspiration" + return {'FINISHED'} + + ed = context.scene.sequence_editor + if ed and len(ed.sequences) > 0: + ed.sequences[0].filepath = filename + else: + bpy.ops.sequencer.movie_strip_add(path=filename) + + context.scene.render.file_format = 'AVI_JPEG' + context.scene.thinking = "make a movie button is done" + rd = context.scene.render + rd.render_stamp = True + rd.stamp_time = False + rd.stamp_date = False + rd.stamp_render_time = False + rd.stamp_frame = False + rd.stamp_scene = False + rd.stamp_camera = False + rd.stamp_filename = False + rd.stamp_marker = False + rd.stamp_sequencer_strip = False + rd.stamp_background = [1, 0, 0, 1] + rd.stamp_foreground = [0, 1, 0, 1] + rd.stamp_font_size = 16 + rd.stamp_note = True + rd.stamp_note_text = about.upper() + ", directed by " + getpass.getuser() + + bpy.ops.render.render('INVOKE_DEFAULT', animation=True) + except: + context.scene.render.render_stamp = False + context.scene.thinking = "make a movie button is out of inspiration" + + return {'FINISHED'} + +def panel_func(self, context): + if bpy.data.filename.find(".B25.blend") != -1: + layout = self.layout + + layout.separator() + layout.separator() + layout.operator("render.make_a_movie", icon='RENDER_ANIMATION') + layout.prop(context.scene, "about") + + layout.label(text=context.scene.thinking) + +subjects = ["Dreaming Elephants", "A Big Bunny", "Flying Pigs"] +about = subjects[random.randint(0, len(subjects)-1)] + +bpy.types.RENDER_PT_render.append(panel_func) +bpy.types.Scene.StringProperty(name="About", default=about, attr="about") +bpy.types.Scene.StringProperty(name="Thinking", default="Status:", attr="thinking") classes = [ EditExternally, SaveDirty, ProjectEdit, - ProjectApply] - + ProjectApply, + MakeAMovie] def register(): register = bpy.types.register diff --git a/release/scripts/ui/space_image.py b/release/scripts/ui/space_image.py index 2f7a64790b4..626188a1b97 100644 --- a/release/scripts/ui/space_image.py +++ b/release/scripts/ui/space_image.py @@ -252,7 +252,7 @@ class IMAGE_HT_header(bpy.types.Header): iuser = sima.image_user toolsettings = context.tool_settings - # show_render = sima.show_render + show_render = sima.show_render # show_paint = sima.show_paint show_uvedit = sima.show_uvedit @@ -276,7 +276,8 @@ class IMAGE_HT_header(bpy.types.Header): sub.menu("IMAGE_MT_uvs") layout.template_ID(sima, "image", new="image.new") - layout.prop(sima, "image_pin", text="") + if not show_render: + layout.prop(sima, "image_pin", text="") # uv editing if show_uvedit: diff --git a/release/scripts/ui/space_info.py b/release/scripts/ui/space_info.py index 4ce0c5becad..e1dccc0c9f0 100644 --- a/release/scripts/ui/space_info.py +++ b/release/scripts/ui/space_info.py @@ -241,7 +241,7 @@ class INFO_MT_add(bpy.types.Menu): if(len(bpy.data.groups) > 10): layout.operator_context = 'INVOKE_DEFAULT' - layout.operator("object.group_instance_add", "type", text="Group Instance...", icon='OUTLINER_OB_EMPTY') + layout.operator("object.group_instance_add", text="Group Instance...", icon='OUTLINER_OB_EMPTY') else: layout.operator_menu_enum("object.group_instance_add", "type", text="Group Instance", icon='OUTLINER_OB_EMPTY')