Compare commits
54 Commits
6.15.4.320
...
6.16
| Author | SHA1 | Date | |
|---|---|---|---|
| c12adecf9f | |||
| fc6013c5de | |||
| 3dd9f07fe2 | |||
| 5308fdd0b8 | |||
| 273d1e296c | |||
| 152af7dc7b | |||
| 43b34f22a3 | |||
| 3330b451d0 | |||
| 5290296952 | |||
| 8fc784aef5 | |||
| 110c8b890b | |||
| b6c686d770 | |||
| 6358db88ff | |||
| b2611fd613 | |||
| 5eb3af0188 | |||
| ad71c17f77 | |||
| 0d7dec8e4e | |||
| 112fbbfc08 | |||
| 4ee5240c72 | |||
| 025e359394 | |||
| 143bcfad08 | |||
| a39ebd13e0 | |||
| e7c0a5f19f | |||
| f0b03dc426 | |||
| 3d2ad79b6b | |||
| 9f28a93c56 | |||
| 386dd1d799 | |||
| e85ebf3a50 | |||
| 81eb2e6f42 | |||
| 9d021a2ec1 | |||
| 439fac65e2 | |||
| dee484a16b | |||
| 90457d6f20 | |||
| 245c30d7a7 | |||
| 81b28293ca | |||
| 392f71b214 | |||
| 257a5281ed | |||
| d44f70a145 | |||
| ec9198f25d | |||
| 1ffd4f97fc | |||
| e8968252ab | |||
| ae618ddd76 | |||
| 005aa1a64c | |||
| a63231d36f | |||
| db530f7def | |||
| 627261f51d | |||
| d080b71f29 | |||
| f6bfeefc8e | |||
| b0070122f8 | |||
| cc004c00f0 | |||
| 83ad789654 | |||
| 21eaa5ee9c | |||
| fd5ee77f1c | |||
| b9acbfccd7 |
@@ -4,7 +4,7 @@ label add_file:
|
||||
import os
|
||||
import codecs
|
||||
|
||||
filename = interface.input(_("FILENAME"), _("Enter the name of the script file to create."), filename="withslash")
|
||||
filename = interface.input(_("FILENAME"), _("Enter the name of the script file to create."), filename="withslash", cancel=Jump("navigation"))
|
||||
|
||||
if "." in filename and not filename.endswith(".rpy"):
|
||||
interface.error(_("The filename must have the .rpy extension."), label="navigation")
|
||||
|
||||
@@ -47,7 +47,7 @@ init python in distribute:
|
||||
regexp += r'.*'
|
||||
pattern = pattern[2:]
|
||||
elif pattern[0] == "*":
|
||||
regexp += r'[^/]*'
|
||||
regexp += r'[^/]*/?'
|
||||
pattern = pattern[1:]
|
||||
elif pattern[0] == '[':
|
||||
regexp += r'['
|
||||
@@ -167,8 +167,8 @@ init python in distribute:
|
||||
if (not i.directory) or (i.name in needed_dirs):
|
||||
rv.insert(0, i.copy())
|
||||
|
||||
directory, _sep, _filename = i.name.rpartition("/")
|
||||
needed_dirs.add(directory)
|
||||
directory, _sep, _filename = i.name.rpartition("/")
|
||||
needed_dirs.add(directory)
|
||||
|
||||
return rv
|
||||
|
||||
|
||||
@@ -174,7 +174,14 @@ init -1 python hide:
|
||||
|
||||
_game_menu_screen = None
|
||||
|
||||
config.underlay = [ ]
|
||||
config.underlay = [
|
||||
renpy.Keymap(
|
||||
quit = renpy.quit_event,
|
||||
iconify = renpy.iconify,
|
||||
choose_renderer = renpy.curried_call_in_new_context("_choose_renderer"),
|
||||
),
|
||||
]
|
||||
|
||||
config.rollback_enabled = False
|
||||
|
||||
|
||||
|
||||
@@ -103,9 +103,9 @@ init python in distribute:
|
||||
zi.create_system = 3
|
||||
|
||||
if xbit:
|
||||
zi.external_attr = long(0100777) << 16
|
||||
zi.external_attr = long(0100755) << 16
|
||||
else:
|
||||
zi.external_attr = long(0100666) << 16
|
||||
zi.external_attr = long(0100644) << 16
|
||||
|
||||
self.zipfile.write_with_info(zi, path)
|
||||
|
||||
@@ -119,7 +119,7 @@ init python in distribute:
|
||||
zi.date_time = time.gmtime(s.st_mtime)[:6]
|
||||
zi.compress_type = zipfile.ZIP_STORED
|
||||
zi.create_system = 3
|
||||
zi.external_attr = (long(0040777) << 16) | 0x10
|
||||
zi.external_attr = (long(0040755) << 16) | 0x10
|
||||
|
||||
self.zipfile.write_with_info(zi, path)
|
||||
|
||||
@@ -150,9 +150,9 @@ init python in distribute:
|
||||
info.type = tarfile.DIRTYPE
|
||||
|
||||
if xbit:
|
||||
info.mode = 0777
|
||||
info.mode = 0755
|
||||
else:
|
||||
info.mode = 0666
|
||||
info.mode = 0644
|
||||
|
||||
info.uid = 1000
|
||||
info.gid = 1000
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
init -999:
|
||||
$ config.script_version = (6, 15, 4)
|
||||
$ config.script_version = (6, 15, 7)
|
||||
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ label translate:
|
||||
|
||||
python:
|
||||
|
||||
language = interface.input(_("Create or Update Translations"), _("Please enter the name of the language for which you want to create or update translations."), filename=True, default=persistent.translate_language)
|
||||
language = interface.input(_("Create or Update Translations"), _("Please enter the name of the language for which you want to create or update translations."), filename=True, default=persistent.translate_language, cancel=Jump("front_page"))
|
||||
|
||||
language = language.strip()
|
||||
|
||||
|
||||
+228
-19
@@ -25,12 +25,12 @@
|
||||
#include <libavutil/avstring.h>
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavcodec/avcodec.h>
|
||||
// #include "libavdevice/avdevice.h"
|
||||
#include <libswscale/swscale.h>
|
||||
// #include "libavcodec/audioconvert.h"
|
||||
// #include "libavcodec/opt.h"
|
||||
|
||||
// #include "cmdutils.h"
|
||||
#ifdef HAS_RESAMPLE
|
||||
#include <libavutil/opt.h>
|
||||
#include <libavresample/avresample.h>
|
||||
#endif
|
||||
|
||||
#include <SDL.h>
|
||||
#include <SDL_thread.h>
|
||||
@@ -100,17 +100,24 @@ typedef struct VideoState {
|
||||
/* samples output by the codec. we reserve more space for avsync
|
||||
compensation */
|
||||
|
||||
#ifndef HAS_RESAMPLE
|
||||
uint8_t audio_buf1[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2] __attribute__ ((aligned (16))) ;
|
||||
uint8_t audio_buf2[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2] __attribute__ ((aligned (16))) ;
|
||||
|
||||
#else
|
||||
uint8_t *audio_buf1;
|
||||
#endif
|
||||
uint8_t *audio_buf;
|
||||
|
||||
unsigned int audio_buf_size; /* in bytes */
|
||||
|
||||
int audio_buf_index; /* in bytes */
|
||||
AVPacket audio_pkt;
|
||||
AVPacket audio_pkt_temp;
|
||||
|
||||
// AVAudioConvert *reformat_ctx;
|
||||
#ifndef HAS_RESAMPLE
|
||||
ReSampleContext *reformat_ctx;
|
||||
#endif
|
||||
int resample_frac;
|
||||
|
||||
int show_audio; /* if true, display audio samples */
|
||||
@@ -165,6 +172,19 @@ typedef struct VideoState {
|
||||
// Should we force the display of the current video frame?
|
||||
int first_frame;
|
||||
|
||||
#ifdef HAS_RESAMPLE
|
||||
// The audio frame, and the audio resample context.
|
||||
enum AVSampleFormat sdl_sample_fmt;
|
||||
uint64_t sdl_channel_layout;
|
||||
int sdl_channels;
|
||||
int sdl_sample_rate;
|
||||
enum AVSampleFormat resample_sample_fmt;
|
||||
uint64_t resample_channel_layout;
|
||||
int resample_sample_rate;
|
||||
AVAudioResampleContext *avr;
|
||||
AVFrame *frame;
|
||||
#endif
|
||||
|
||||
} VideoState;
|
||||
|
||||
SDL_mutex *codec_mutex = NULL;
|
||||
@@ -183,7 +203,6 @@ static int debug_mv = 0;
|
||||
static int workaround_bugs = 1;
|
||||
static int fast = 0;
|
||||
static int genpts = 0;
|
||||
static int lowres = 0;
|
||||
static int idct = FF_IDCT_AUTO;
|
||||
static enum AVDiscard skip_frame= AVDISCARD_DEFAULT;
|
||||
static enum AVDiscard skip_idct= AVDISCARD_DEFAULT;
|
||||
@@ -770,8 +789,181 @@ static int video_thread(void *arg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HAS_RESAMPLE
|
||||
|
||||
/* decode one audio frame and returns its uncompressed size */
|
||||
static int audio_decode_frame(VideoState *is, double *pts_ptr)
|
||||
{
|
||||
AVPacket *pkt_temp = &is->audio_pkt_temp;
|
||||
AVPacket *pkt = &is->audio_pkt;
|
||||
AVCodecContext *dec = is->audio_st->codec;
|
||||
int n, len1, data_size, got_frame;
|
||||
double pts;
|
||||
int new_packet = 0;
|
||||
int flush_complete = 0;
|
||||
|
||||
for (;;) {
|
||||
/* NOTE: the audio packet can contain several frames */
|
||||
while (pkt_temp->size > 0 || (!pkt_temp->data && new_packet)) {
|
||||
int resample_changed, audio_resample;
|
||||
|
||||
if (!is->frame) {
|
||||
if (!(is->frame = avcodec_alloc_frame()))
|
||||
return AVERROR(ENOMEM);
|
||||
} else
|
||||
avcodec_get_frame_defaults(is->frame);
|
||||
|
||||
if (flush_complete)
|
||||
break;
|
||||
new_packet = 0;
|
||||
len1 = avcodec_decode_audio4(dec, is->frame, &got_frame, pkt_temp);
|
||||
if (len1 < 0) {
|
||||
/* if error, we skip the frame */
|
||||
pkt_temp->size = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
pkt_temp->data += len1;
|
||||
pkt_temp->size -= len1;
|
||||
|
||||
if (!got_frame) {
|
||||
/* stop sending empty packets if the decoder is finished */
|
||||
if (!pkt_temp->data && dec->codec->capabilities & CODEC_CAP_DELAY)
|
||||
flush_complete = 1;
|
||||
continue;
|
||||
}
|
||||
data_size = av_samples_get_buffer_size(NULL, dec->channels,
|
||||
is->frame->nb_samples,
|
||||
is->frame->format, 1);
|
||||
|
||||
audio_resample = is->frame->format != is->sdl_sample_fmt ||
|
||||
is->frame->channel_layout != is->sdl_channel_layout ||
|
||||
is->frame->sample_rate != is->sdl_sample_rate;
|
||||
|
||||
resample_changed = is->frame->format != is->resample_sample_fmt ||
|
||||
is->frame->channel_layout != is->resample_channel_layout ||
|
||||
is->frame->sample_rate != is->resample_sample_rate;
|
||||
|
||||
if ((!is->avr && audio_resample) || resample_changed) {
|
||||
int ret;
|
||||
if (is->avr)
|
||||
avresample_close(is->avr);
|
||||
else if (audio_resample) {
|
||||
is->avr = avresample_alloc_context();
|
||||
if (!is->avr) {
|
||||
fprintf(stderr, "error allocating AVAudioResampleContext\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (audio_resample) {
|
||||
av_opt_set_int(is->avr, "in_channel_layout", is->frame->channel_layout, 0);
|
||||
av_opt_set_int(is->avr, "in_sample_fmt", is->frame->format, 0);
|
||||
av_opt_set_int(is->avr, "in_sample_rate", is->frame->sample_rate, 0);
|
||||
av_opt_set_int(is->avr, "out_channel_layout", is->sdl_channel_layout, 0);
|
||||
av_opt_set_int(is->avr, "out_sample_fmt", is->sdl_sample_fmt, 0);
|
||||
av_opt_set_int(is->avr, "out_sample_rate", is->sdl_sample_rate, 0);
|
||||
|
||||
if ((ret = avresample_open(is->avr)) < 0) {
|
||||
fprintf(stderr, "error initializing libavresample\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
is->resample_sample_fmt = is->frame->format;
|
||||
is->resample_channel_layout = is->frame->channel_layout;
|
||||
is->resample_sample_rate = is->frame->sample_rate;
|
||||
}
|
||||
|
||||
if (audio_resample) {
|
||||
void *tmp_out;
|
||||
int out_samples, out_size, out_linesize;
|
||||
int osize = av_get_bytes_per_sample(is->sdl_sample_fmt);
|
||||
int nb_samples = is->frame->nb_samples;
|
||||
|
||||
int max_samples = 2 * (avresample_get_delay(is->avr) + nb_samples) * is->sdl_sample_rate / is->frame->sample_rate;
|
||||
|
||||
|
||||
out_size = av_samples_get_buffer_size(
|
||||
&out_linesize,
|
||||
is->sdl_channels,
|
||||
max_samples,
|
||||
is->sdl_sample_fmt, 0);
|
||||
|
||||
tmp_out = av_realloc(is->audio_buf1, out_size);
|
||||
|
||||
if (!tmp_out)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
is->audio_buf1 = tmp_out;
|
||||
|
||||
out_samples = avresample_convert(is->avr,
|
||||
&is->audio_buf1,
|
||||
out_linesize, max_samples,
|
||||
is->frame->data,
|
||||
is->frame->linesize[0],
|
||||
is->frame->nb_samples);
|
||||
|
||||
if (out_samples < 0) {
|
||||
fprintf(stderr, "avresample_convert() failed\n");
|
||||
break;
|
||||
}
|
||||
is->audio_buf = is->audio_buf1;
|
||||
data_size = out_samples * osize * is->sdl_channels;
|
||||
} else {
|
||||
is->audio_buf = is->frame->data[0];
|
||||
}
|
||||
|
||||
/* if no pts, then compute it */
|
||||
pts = is->audio_clock;
|
||||
*pts_ptr = pts;
|
||||
n = is->sdl_channels * av_get_bytes_per_sample(is->sdl_sample_fmt);
|
||||
is->audio_clock += (double)data_size /
|
||||
(double)(n * is->sdl_sample_rate);
|
||||
|
||||
// This is Ren'Py specific code, to deal with ogg files with
|
||||
// more data than their duration.
|
||||
if (is->audio_duration) {
|
||||
int len = data_size / 4;
|
||||
int maxlen = is->audio_duration - is->audio_played;
|
||||
|
||||
if (len > maxlen) {
|
||||
len = maxlen;
|
||||
}
|
||||
|
||||
is->audio_played += len;
|
||||
data_size = len * 4;
|
||||
}
|
||||
|
||||
return data_size;
|
||||
}
|
||||
|
||||
/* free the current packet */
|
||||
if (pkt->data)
|
||||
av_free_packet(pkt);
|
||||
memset(pkt_temp, 0, sizeof(*pkt_temp));
|
||||
|
||||
if (is->paused || is->audioq.abort_request) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* read next packet */
|
||||
if ((new_packet = packet_queue_get(&is->audioq, pkt, 1)) < 0)
|
||||
return -1;
|
||||
|
||||
if (pkt->data == flush_pkt.data) {
|
||||
avcodec_flush_buffers(dec);
|
||||
flush_complete = 0;
|
||||
}
|
||||
|
||||
*pkt_temp = *pkt;
|
||||
|
||||
/* if update the audio clock with the pts */
|
||||
if (pkt->pts != AV_NOPTS_VALUE) {
|
||||
is->audio_clock = av_q2d(is->audio_st->time_base)*pkt->pts;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* decode one audio frame and returns its uncompressed size */
|
||||
static int audio_decode_frame(VideoState *is, double *pts_ptr)
|
||||
@@ -823,17 +1015,17 @@ static int audio_decode_frame(VideoState *is, double *pts_ptr)
|
||||
}
|
||||
|
||||
// Moved by tom, from below next block. Is this right?
|
||||
|
||||
|
||||
|
||||
if (is->reformat_ctx) {
|
||||
|
||||
|
||||
int len = data_size / av_get_bytes_per_sample(dec->sample_fmt);
|
||||
len /= dec->channels;
|
||||
|
||||
len = audio_resample(is->reformat_ctx, (short *) is->audio_buf2, (short *) is->audio_buf1, len);
|
||||
|
||||
data_size = len * 4;
|
||||
is->audio_buf = is->audio_buf2;
|
||||
is->audio_buf = is->audio_buf2;
|
||||
} else {
|
||||
is->audio_buf = is->audio_buf1;
|
||||
}
|
||||
@@ -846,7 +1038,7 @@ static int audio_decode_frame(VideoState *is, double *pts_ptr)
|
||||
int inpos;
|
||||
|
||||
int len = data_size / 4;
|
||||
|
||||
|
||||
if (is->audio_buf == is->audio_buf1) {
|
||||
in = (short *) is->audio_buf1;
|
||||
out = (short *) is->audio_buf2;
|
||||
@@ -860,9 +1052,9 @@ static int audio_decode_frame(VideoState *is, double *pts_ptr)
|
||||
// which seems reasonable.
|
||||
in[2 * len] = 2 * in[2 * len - 2] - in[2 * len - 4];
|
||||
in[2 * len + 1] = 2 * in[2 * len - 1] - in[2 * len - 3];
|
||||
|
||||
|
||||
// The number of bytes of input consumed per output
|
||||
// sample. Scaled by 1 << 14.
|
||||
// sample. Scaled by 1 << 14.
|
||||
in_per_out = (dec->sample_rate << 14) / audio_sample_rate;
|
||||
|
||||
len *= (1 << 14);
|
||||
@@ -892,14 +1084,14 @@ static int audio_decode_frame(VideoState *is, double *pts_ptr)
|
||||
out[2 * outpos + 1] = a + (((b - a) * frac) >> 14);
|
||||
|
||||
outpos++;
|
||||
inpos += in_per_out;
|
||||
inpos += in_per_out;
|
||||
}
|
||||
|
||||
// Store the fraction.
|
||||
is->resample_frac = inpos & ((1 << 14) - 1);
|
||||
|
||||
data_size = outpos * 4;
|
||||
is->audio_buf = (uint8_t *) out;
|
||||
is->audio_buf = (uint8_t *) out;
|
||||
}
|
||||
|
||||
|
||||
@@ -915,7 +1107,7 @@ static int audio_decode_frame(VideoState *is, double *pts_ptr)
|
||||
if (is->audio_duration) {
|
||||
int len = data_size / 4;
|
||||
int maxlen = is->audio_duration - is->audio_played;
|
||||
|
||||
|
||||
if (len > maxlen) {
|
||||
len = maxlen;
|
||||
}
|
||||
@@ -923,7 +1115,7 @@ static int audio_decode_frame(VideoState *is, double *pts_ptr)
|
||||
is->audio_played += len;
|
||||
data_size = len * 4;
|
||||
}
|
||||
|
||||
|
||||
return data_size;
|
||||
}
|
||||
|
||||
@@ -953,6 +1145,9 @@ static int audio_decode_frame(VideoState *is, double *pts_ptr)
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* get the current audio output buffer size, in samples. With SDL, we
|
||||
cannot have a precise information */
|
||||
static int audio_write_get_buf_size(VideoState *is)
|
||||
@@ -1038,8 +1233,6 @@ static int stream_component_open(VideoState *is, int stream_index)
|
||||
enc->debug_mv = debug_mv;
|
||||
enc->debug = debug;
|
||||
enc->workaround_bugs = workaround_bugs;
|
||||
enc->lowres = lowres;
|
||||
if(lowres) enc->flags |= CODEC_FLAG_EMU_EDGE;
|
||||
enc->idct_algo= idct;
|
||||
if(fast) enc->flags2 |= CODEC_FLAG2_FAST;
|
||||
enc->skip_frame= skip_frame;
|
||||
@@ -1069,6 +1262,20 @@ static int stream_component_open(VideoState *is, int stream_index)
|
||||
is->audio_buf_size = 0;
|
||||
is->audio_buf_index = 0;
|
||||
|
||||
#ifdef HAS_RESAMPLE
|
||||
if (!enc->channel_layout)
|
||||
enc->channel_layout = av_get_default_channel_layout(enc->channels);
|
||||
if (!enc->channel_layout) {
|
||||
fprintf(stderr, "%s: unable to guess channel layout\n", is->filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
is->sdl_sample_rate = audio_sample_rate;
|
||||
is->sdl_channel_layout = AV_CH_LAYOUT_STEREO;
|
||||
is->sdl_channels = av_get_channel_layout_nb_channels(is->sdl_channel_layout);
|
||||
is->sdl_sample_fmt = AV_SAMPLE_FMT_S16;
|
||||
#endif
|
||||
|
||||
memset(&is->audio_pkt, 0, sizeof(is->audio_pkt));
|
||||
packet_queue_init(&is->audioq);
|
||||
break;
|
||||
@@ -1102,8 +1309,10 @@ static void stream_component_close(VideoState *is, int stream_index)
|
||||
case AVMEDIA_TYPE_AUDIO:
|
||||
packet_queue_abort(&is->audioq);
|
||||
packet_queue_end(&is->audioq);
|
||||
#ifndef HAS_RESAMPLE
|
||||
if (is->reformat_ctx)
|
||||
audio_resample_close(is->reformat_ctx);
|
||||
#endif
|
||||
break;
|
||||
case AVMEDIA_TYPE_VIDEO:
|
||||
packet_queue_abort(&is->videoq);
|
||||
@@ -1353,7 +1562,7 @@ fail:
|
||||
if (is->video_stream >= 0)
|
||||
stream_component_close(is, is->video_stream);
|
||||
if (is->ic) {
|
||||
av_close_input_file(is->ic);
|
||||
avformat_close_input(&(is->ic));
|
||||
is->ic = NULL;
|
||||
}
|
||||
|
||||
|
||||
+4
-1
@@ -12,7 +12,7 @@
|
||||
|
||||
#if defined ANDROID
|
||||
|
||||
#define RENPY_GLES_1
|
||||
#define RENPY_GLES_2
|
||||
|
||||
#elif defined ANGLE
|
||||
|
||||
@@ -54,7 +54,10 @@
|
||||
|
||||
#if defined RENPY_GLES_2
|
||||
|
||||
#ifndef ANDROID
|
||||
#include <EGL/egl.h>
|
||||
#endif
|
||||
|
||||
#include <GLES2/gl2.h>
|
||||
|
||||
typedef GLuint GLhandleARB;
|
||||
|
||||
+19
-16
@@ -373,25 +373,28 @@ cdef extern from "pyfreetype.h":
|
||||
FT_Error FT_Set_Char_Size(FT_Face, FT_F26Dot6 char_width, FT_F26Dot6 char_height, FT_UInt hres, FT_UInt vres)
|
||||
FT_Error FT_Set_Pixel_Sizes(FT_Face face, FT_UInt pixel_width, FT_UInt pixel_height)
|
||||
|
||||
ctypedef enum FT_Load_Flags:
|
||||
FT_LOAD_DEFAULT
|
||||
FT_LOAD_NO_SCALE
|
||||
FT_LOAD_NO_HINTING
|
||||
FT_LOAD_RENDER
|
||||
FT_LOAD_NO_BITMAP
|
||||
FT_LOAD_VERTICAL_LAYOUT
|
||||
FT_LOAD_FORCE_AUTOHINT
|
||||
FT_LOAD_CROP_BITMAP
|
||||
FT_LOAD_PEDANTIC
|
||||
FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH
|
||||
FT_LOAD_NO_RECURSE
|
||||
FT_LOAD_IGNORE_TRANSFORM
|
||||
FT_LOAD_MONOCHROME
|
||||
FT_LOAD_LINEAR_DESIGN
|
||||
FT_LOAD_SBITS_ONLY
|
||||
FT_LOAD_NO_AUTOHINT
|
||||
|
||||
FT_Error FT_Load_Glyph(FT_Face face, FT_UInt glyph_index, FT_Int32 flags)
|
||||
FT_Error FT_Load_Char(FT_Face face, FT_ULong char_code, FT_Int32 flags)
|
||||
|
||||
DEF FT_LOAD_DEFAULT = 0
|
||||
DEF FT_LOAD_NO_SCALE = 1 << 0
|
||||
DEF FT_LOAD_NO_HINTING = 1 << 1
|
||||
DEF FT_LOAD_RENDER = 1 << 2
|
||||
DEF FT_LOAD_NO_BITMAP = 1 << 3
|
||||
DEF FT_LOAD_VERTICAL_LAYOUT = 1 << 4
|
||||
DEF FT_LOAD_FORCE_AUTOHINT = 1 << 5
|
||||
DEF FT_LOAD_CROP_BITMAP = 1 << 6
|
||||
DEF FT_LOAD_PEDANTIC = 1 << 7
|
||||
DEF FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH = 1 << 9
|
||||
DEF FT_LOAD_NO_RECURSE = 1 << 10
|
||||
DEF FT_LOAD_IGNORE_TRANSFORM = 1 << 11
|
||||
DEF FT_LOAD_MONOCHROME = 1 << 12
|
||||
DEF FT_LOAD_LINEAR_DESIGN = 1 << 13
|
||||
DEF FT_LOAD_SBITS_ONLY = 1 << 14
|
||||
DEF FT_LOAD_NO_AUTOHINT = 1 << 15
|
||||
|
||||
|
||||
void FT_Set_Transform(FT_Face face, FT_Matrix *matrix, FT_Vector *delta)
|
||||
|
||||
|
||||
+14
-6
@@ -37,6 +37,7 @@ library("png")
|
||||
library("avformat")
|
||||
library("avcodec")
|
||||
library("avutil")
|
||||
has_avresample = library("avresample", optional=True)
|
||||
has_swscale = library("swscale", optional=True)
|
||||
library("freetype")
|
||||
has_fribidi = library("fribidi", optional=True)
|
||||
@@ -46,7 +47,7 @@ has_libglew32 = library("glew32", optional=True)
|
||||
has_angle = windows and library("EGL", optional=True) and library("GLESv2", optional=True)
|
||||
|
||||
if android:
|
||||
sdl = [ 'sdl', 'GLESv1_CM', 'log' ]
|
||||
sdl = [ 'sdl', 'GLESv2', 'log' ]
|
||||
else:
|
||||
sdl = [ 'SDL' ]
|
||||
|
||||
@@ -69,13 +70,20 @@ pymodule("pysdlsound.__init__")
|
||||
if not android:
|
||||
|
||||
sound = [ "avformat", "avcodec", "avutil", "z" ]
|
||||
macros = [ ]
|
||||
|
||||
if has_avresample:
|
||||
sound.insert(0, "avresample")
|
||||
macros.append(("HAS_RESAMPLE", 1))
|
||||
|
||||
if has_swscale:
|
||||
sound.insert(0, "swscale")
|
||||
|
||||
|
||||
cython(
|
||||
"pysdlsound.sound",
|
||||
[ "pss.c", "ffdecode.c" ],
|
||||
libs = sdl + sound)
|
||||
libs = sdl + sound,
|
||||
define_macros=macros)
|
||||
|
||||
|
||||
# Display.
|
||||
@@ -84,7 +92,7 @@ cython("renpy.display.accelerator", libs=sdl + [ 'z', 'm' ])
|
||||
|
||||
# Gl.
|
||||
if android:
|
||||
glew_libs = [ 'GLESv1_CM', 'z', 'm' ]
|
||||
glew_libs = [ 'GLESv2', 'z', 'm' ]
|
||||
elif has_libglew:
|
||||
glew_libs = [ 'GLEW' ]
|
||||
else:
|
||||
@@ -92,9 +100,9 @@ else:
|
||||
|
||||
cython("renpy.gl.gldraw", libs=glew_libs )
|
||||
cython("renpy.gl.gltexture", libs=glew_libs)
|
||||
cython("renpy.gl.glenviron_shader", libs=glew_libs)
|
||||
cython("renpy.gl.glenviron_fixed", libs=glew_libs, compile_if=not android)
|
||||
cython("renpy.gl.glenviron_shader", libs=glew_libs, compile_if=not android)
|
||||
cython("renpy.gl.glenviron_limited", libs=glew_libs)
|
||||
cython("renpy.gl.glenviron_limited", libs=glew_libs, compile_if=not android)
|
||||
cython("renpy.gl.glrtt_copy", libs=glew_libs)
|
||||
cython("renpy.gl.glrtt_fbo", libs=glew_libs)
|
||||
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
#!/usr/bin/env python
|
||||
#@PydevCodeAnalysisIgnore
|
||||
|
||||
# This file is part of Ren'Py. The license below applies to Ren'Py only.
|
||||
# Games and other projects that use Ren'Py may use a different license.
|
||||
|
||||
# Copyright 2004-2012 Tom Rothamel <pytom@bishoujo.us>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
@@ -37,6 +41,26 @@ def path_to_common(renpy_base):
|
||||
def path_to_saves(gamedir):
|
||||
import renpy #@UnresolvedImport
|
||||
|
||||
# Android.
|
||||
if renpy.android:
|
||||
paths = [
|
||||
os.path.join(os.environ["ANDROID_OLD_PUBLIC"], "game/saves"),
|
||||
os.path.join(os.environ["ANDROID_PRIVATE"], "saves"),
|
||||
os.path.join(os.environ["ANDROID_PUBLIC"], "saves"),
|
||||
]
|
||||
|
||||
for rv in paths:
|
||||
if os.path.isdir(rv):
|
||||
break
|
||||
|
||||
print "Using savedir", rv
|
||||
|
||||
# We return the last path as the default.
|
||||
|
||||
return rv
|
||||
|
||||
|
||||
# No save directory given.
|
||||
if not renpy.config.save_directory:
|
||||
return gamedir + "/saves"
|
||||
|
||||
@@ -54,10 +78,7 @@ def path_to_saves(gamedir):
|
||||
path = newpath
|
||||
|
||||
# Otherwise, put the saves in a platform-specific location.
|
||||
if renpy.android:
|
||||
return gamedir + "/saves"
|
||||
|
||||
elif renpy.macintosh:
|
||||
if renpy.macintosh:
|
||||
rv = "~/Library/RenPy/" + renpy.config.save_directory
|
||||
return os.path.expanduser(rv)
|
||||
|
||||
@@ -107,7 +128,6 @@ if android:
|
||||
__main__.path_to_common = path_to_common
|
||||
__main__.path_to_saves = path_to_saves
|
||||
os.environ["RENPY_RENDERER"] = "gl"
|
||||
os.environ["RENPY_GL_ENVIRON"] = "limited"
|
||||
|
||||
def main():
|
||||
|
||||
|
||||
+2
-2
@@ -34,9 +34,9 @@ except ImportError:
|
||||
# The tuple giving the version. This needs to be updated when
|
||||
# we bump the version.
|
||||
#
|
||||
# Be sure to change script_version in launcher/script_version.rpy.
|
||||
# Be sure to change script_version in launcher/game/script_version.rpy.
|
||||
# Be sure to change config.version in tutorial/game/options.rpy.
|
||||
version_tuple = (6, 15, 4, vc_version)
|
||||
version_tuple = (6, 15, 7, vc_version)
|
||||
|
||||
# A verbose string computed from that version.
|
||||
version = "Ren'Py " + ".".join(str(i) for i in version_tuple)
|
||||
|
||||
+1
-1
@@ -278,7 +278,7 @@ class Node(object):
|
||||
be executed after this one.
|
||||
"""
|
||||
|
||||
assert False, "Node subclass forgot to define execute."
|
||||
raise Exception("Node subclass forgot to define execute.")
|
||||
|
||||
def early_execute(self):
|
||||
"""
|
||||
|
||||
@@ -75,6 +75,7 @@ PROPERTIES = {
|
||||
"yzoom" : float,
|
||||
"zoom" : float,
|
||||
"alpha" : float,
|
||||
"additive" : float,
|
||||
"around" : (position, position),
|
||||
"alignaround" : (float, float),
|
||||
"angle" : float,
|
||||
|
||||
+23
-6
@@ -87,12 +87,15 @@ class NullFile(io.IOBase):
|
||||
raise IOError("Not implemented.")
|
||||
|
||||
def null_files():
|
||||
if sys.stderr.fileno() < 0:
|
||||
sys.stderr = NullFile()
|
||||
try:
|
||||
if sys.stderr.fileno() < 0:
|
||||
sys.stderr = NullFile()
|
||||
|
||||
if sys.stdout.fileno() < 0:
|
||||
sys.stdout = NullFile()
|
||||
except:
|
||||
pass
|
||||
|
||||
if sys.stdout.fileno() < 0:
|
||||
sys.stdout = NullFile()
|
||||
|
||||
null_files()
|
||||
|
||||
|
||||
@@ -250,6 +253,14 @@ this program do not contain : or ; in their names.
|
||||
renpy.config.basedir = basedir
|
||||
renpy.config.gamedir = gamedir
|
||||
renpy.config.args = [ ]
|
||||
|
||||
if renpy.android:
|
||||
renpy.config.logdir = os.environ['ANDROID_PUBLIC']
|
||||
else:
|
||||
renpy.config.logdir = basedir
|
||||
|
||||
if not os.path.exists(renpy.config.logdir):
|
||||
os.makedirs(renpy.config.logdir, 0777)
|
||||
|
||||
renpy.main.main()
|
||||
keep_running = False
|
||||
@@ -370,7 +381,11 @@ def open_error_file(fn, mode):
|
||||
was opened.
|
||||
"""
|
||||
|
||||
import tempfile
|
||||
try:
|
||||
f = file(os.path.join(renpy.config.logdir, fn), mode)
|
||||
return f, fn
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
f = file(fn, mode)
|
||||
@@ -378,6 +393,8 @@ def open_error_file(fn, mode):
|
||||
except:
|
||||
pass
|
||||
|
||||
import tempfile
|
||||
|
||||
fn = os.path.join(tempfile.gettempdir(), "renpy-" + fn)
|
||||
return file(fn, mode), fn
|
||||
|
||||
|
||||
@@ -165,8 +165,16 @@ init -1500 python:
|
||||
Causes the game to begin skipping. If the game is in a menu
|
||||
context, then this returns to the game. Otherwise, it just
|
||||
enables skipping.
|
||||
|
||||
`fast`
|
||||
If True, skips directly to the next menu choice.
|
||||
"""
|
||||
|
||||
|
||||
fast = False
|
||||
|
||||
def __init__(self, fast=False):
|
||||
self.fast = fast
|
||||
|
||||
def __call__(self):
|
||||
if not self.get_sensitive():
|
||||
return
|
||||
@@ -174,7 +182,15 @@ init -1500 python:
|
||||
if renpy.context()._menu:
|
||||
renpy.jump("_return_skipping")
|
||||
else:
|
||||
config.skipping = not config.skipping
|
||||
|
||||
if not config.skipping:
|
||||
if self.fast:
|
||||
config.skipping = "fast"
|
||||
else:
|
||||
config.skipping = "slow"
|
||||
else:
|
||||
config.skipping = None
|
||||
|
||||
renpy.restart_interaction()
|
||||
|
||||
def get_selected(self):
|
||||
|
||||
@@ -49,6 +49,9 @@ init -1900 python:
|
||||
|
||||
# Prefixes to strip from automatic images.
|
||||
config.automatic_images_strip = [ ]
|
||||
|
||||
# The minimum number of components which the image name consists of is 2 by default.
|
||||
config.automatic_images_minimum_components = 2
|
||||
|
||||
|
||||
init 1900 python hide:
|
||||
@@ -86,8 +89,8 @@ init 1900 python hide:
|
||||
else:
|
||||
break
|
||||
|
||||
# Only names of 2 components or more.
|
||||
if len(name) < 2:
|
||||
# Only names of 2 components or more by default.
|
||||
if len(name) < config.automatic_images_minimum_components:
|
||||
continue
|
||||
|
||||
# Reject if it already exists.
|
||||
|
||||
@@ -86,6 +86,9 @@ init -1800 python hide:
|
||||
style.list_text = Style(style.default)
|
||||
|
||||
style.tile = Style(style.default, help='default style of tile')
|
||||
|
||||
# Not used - but some old games might customize it.
|
||||
style.error_root = Style(style.default)
|
||||
|
||||
# The base styles that can be customized by themes.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Copyright 2004-2013 Tom Rothamel <pytom@bishoujo.us>
|
||||
# See LICENSE.txt for license details.
|
||||
|
||||
init python hide:
|
||||
init python:
|
||||
|
||||
style.menu_button = Style(style.button, heavy=True, help='Buttons that are part of the main or game menus.')
|
||||
style.menu_button_text = Style(style.button_text, heavy=True, help='The label of buttons that are part of the main or game menus.')
|
||||
@@ -43,7 +43,6 @@ init python hide:
|
||||
style.yesno_button = Style(style.menu_button, heavy=True, help='A Yes/No button.')
|
||||
style.yesno_button_text = Style(style.menu_button_text, heavy=True, help='A Yes/No button label.')
|
||||
|
||||
|
||||
style.prefs_frame = Style(style.default, heavy=True, help='')
|
||||
style.prefs_pref_frame = Style(style.default, heavy=True, help='')
|
||||
style.prefs_pref_vbox = Style(style.thin_vbox, heavy=True, help='')
|
||||
@@ -323,15 +322,25 @@ init python hide:
|
||||
|
||||
store._selected_compat = [ ]
|
||||
|
||||
class _SelectedCompat(object):
|
||||
class _SelectedCompat(renpy.style.Style):
|
||||
|
||||
def __init__(self, target):
|
||||
self.__dict__["target"] = target
|
||||
self.__dict__["property_updates"] = [ ]
|
||||
|
||||
self.target = target
|
||||
self.property_updates = [ ]
|
||||
|
||||
super(_SelectedCompat, self).__init__(target)
|
||||
|
||||
store._selected_compat.append(self)
|
||||
|
||||
def __setattr__(self, k, v):
|
||||
def setattr(self, k, v):
|
||||
super(_SelectedCompat, self).setattr(k, v)
|
||||
|
||||
try:
|
||||
super(_SelectedCompat, self).setattr("selected_" + k, v)
|
||||
except:
|
||||
pass
|
||||
|
||||
self.property_updates.append((k, v))
|
||||
|
||||
def apply(self):
|
||||
@@ -340,7 +349,8 @@ init python hide:
|
||||
setattr(target, "selected_" + k, v)
|
||||
|
||||
def clear(self):
|
||||
self.__dict__["property_updates"] = [ ]
|
||||
super(_SelectedCompat, self).clear()
|
||||
self.property_updates = [ ]
|
||||
|
||||
|
||||
style.selected_button = _SelectedCompat('button')
|
||||
@@ -350,8 +360,8 @@ init python hide:
|
||||
style.prefs_selected_button = _SelectedCompat('prefs_button')
|
||||
style.prefs_selected_button_text = _SelectedCompat('prefs_button_text')
|
||||
|
||||
def apply_selected_compat():
|
||||
def _apply_selected_compat():
|
||||
for scs in _selected_compat:
|
||||
scs.apply()
|
||||
|
||||
layout.compat_funcs.append(apply_selected_compat)
|
||||
layout.compat_funcs.append(_apply_selected_compat)
|
||||
|
||||
@@ -379,6 +379,7 @@ gamedir = None
|
||||
basedir = None
|
||||
renpy_base = None
|
||||
commondir = None
|
||||
logdir = None # Where log and error files go.
|
||||
|
||||
# Should we enable OpenGL mode?
|
||||
gl_enable = True
|
||||
|
||||
@@ -108,6 +108,7 @@ Solid = renpy.display.imagelike.Solid
|
||||
LiveComposite = renpy.display.layout.LiveComposite
|
||||
LiveCrop = renpy.display.layout.LiveCrop
|
||||
LiveTile = renpy.display.layout.LiveTile
|
||||
Flatten = renpy.display.layout.Flatten
|
||||
|
||||
Null = renpy.display.layout.Null
|
||||
Window = renpy.display.layout.Window
|
||||
|
||||
@@ -255,8 +255,6 @@ def transform_render(self, widtho, heighto, st, at):
|
||||
xo += width / 2.0
|
||||
yo += height / 2.0
|
||||
|
||||
alpha = state.alpha
|
||||
|
||||
rv = Render(width, height)
|
||||
|
||||
# Default case - no transformation matrix.
|
||||
@@ -279,7 +277,8 @@ def transform_render(self, widtho, heighto, st, at):
|
||||
-rydx / inv_det,
|
||||
rxdx / inv_det)
|
||||
|
||||
rv.alpha = alpha
|
||||
rv.alpha = state.alpha
|
||||
rv.over = 1.0 - state.additive
|
||||
rv.clipping = clipping
|
||||
|
||||
pos = (xo, yo)
|
||||
|
||||
@@ -213,7 +213,7 @@ class Displayable(renpy.object.Object):
|
||||
in seconds.
|
||||
"""
|
||||
|
||||
assert False, "Draw not implemented."
|
||||
raise Exception("Render not implemented.")
|
||||
|
||||
def event(self, ev, x, y, st):
|
||||
"""
|
||||
|
||||
@@ -463,9 +463,9 @@ class Drag(renpy.display.core.Displayable, renpy.python.RevertableObject):
|
||||
new_x = par_x - self.grab_x + xo
|
||||
new_y = par_y - self.grab_y + yo
|
||||
new_x = max(new_x, 0)
|
||||
new_x = min(new_x, i.parent_width - i.w)
|
||||
new_x = min(new_x, int(i.parent_width - i.w))
|
||||
new_y = max(new_y, 0)
|
||||
new_y = min(new_y, i.parent_height - i.h)
|
||||
new_y = min(new_y, int(i.parent_height - i.h))
|
||||
|
||||
if i.drag_group is not None and i.drag_name is not None:
|
||||
i.drag_group.positions[i.drag_name] = (new_x, new_y)
|
||||
|
||||
@@ -294,11 +294,9 @@ def horiz_line_dist(ax0, ay0, ax1, ay1, bx0, by0, bx1, by1):
|
||||
# The right end of a is to the left of the left end of b.
|
||||
if ax0 <= ax1 <= bx0 <= bx1:
|
||||
return points_dist(ax1, ay1, bx0, by0, renpy.config.focus_crossrange_penalty, 1.0)
|
||||
|
||||
if bx0 <= bx1 <= ax0 <= ax1:
|
||||
else:
|
||||
return points_dist(ax0, ay0, bx1, by1, renpy.config.focus_crossrange_penalty, 1.0)
|
||||
|
||||
assert False
|
||||
|
||||
# This computes the distance between two vertical lines. (So the
|
||||
# distance is either hortizontal, or has a horizontal component to it.)
|
||||
@@ -316,13 +314,9 @@ def verti_line_dist(ax0, ay0, ax1, ay1, bx0, by0, bx1, by1):
|
||||
# The right end of a is to the left of the left end of b.
|
||||
if ay0 <= ay1 <= by0 <= by1:
|
||||
return points_dist(ax1, ay1, bx0, by0, 1.0, renpy.config.focus_crossrange_penalty)
|
||||
|
||||
if by0 <= by1 <= ay0 <= ay1:
|
||||
else:
|
||||
return points_dist(ax0, ay0, bx1, by1, 1.0, renpy.config.focus_crossrange_penalty)
|
||||
|
||||
assert False
|
||||
|
||||
|
||||
|
||||
# This focuses the widget that is nearest to the current widget. To
|
||||
# determine nearest, we compute points on the widgets using the
|
||||
|
||||
+1
-1
@@ -458,7 +458,7 @@ class ImageBase(renpy.display.core.Displayable):
|
||||
would override this.
|
||||
"""
|
||||
|
||||
assert False
|
||||
raise Exception("load method not implemented.")
|
||||
|
||||
def render(self, w, h, st, at):
|
||||
|
||||
|
||||
@@ -1742,3 +1742,41 @@ class LiveTile(Container):
|
||||
rv.blit(cr, (x, y), focus=False)
|
||||
|
||||
return rv
|
||||
|
||||
|
||||
class Flatten(Container):
|
||||
"""
|
||||
:doc: disp_imagelike
|
||||
|
||||
This flattens `child`, which may be made up of multiple textures, into
|
||||
a single texture.
|
||||
|
||||
Certain operations, like the alpha transform property, apply to every
|
||||
texture making up a displayable, which can yield incorrect results
|
||||
when the textures overlap on screen. Flatten creates a single texture
|
||||
from multiple textures, which can prevent this problem.
|
||||
|
||||
Flatten is a relatively expensive operation, and so should only be used
|
||||
when absolutely required.
|
||||
"""
|
||||
|
||||
|
||||
def __init__(self, child, **properties):
|
||||
super(Flatten, self).__init__(**properties)
|
||||
|
||||
self.add(child)
|
||||
|
||||
def render(self, width, height, st, at):
|
||||
cr = renpy.display.render.render(self.child, width, height, st, at)
|
||||
cw, ch = cr.get_size()
|
||||
|
||||
tex = cr.render_to_texture(True)
|
||||
|
||||
rv = renpy.display.render.Render(cw, ch)
|
||||
rv.blit(tex, (0, 0))
|
||||
rv.depends_on(cr, focus=True)
|
||||
|
||||
return rv
|
||||
|
||||
|
||||
|
||||
@@ -95,9 +95,11 @@ class TransformState(renpy.object.Object):
|
||||
default_xoffset = None
|
||||
default_yoffset = None
|
||||
transform_anchor = False
|
||||
additive = 0.0
|
||||
|
||||
def __init__(self): # W0231
|
||||
self.alpha = 1
|
||||
self.additive = 0.0
|
||||
self.rotate = None
|
||||
self.rotate_pad = True
|
||||
self.transform_anchor = False
|
||||
@@ -142,6 +144,7 @@ class TransformState(renpy.object.Object):
|
||||
def take_state(self, ts):
|
||||
|
||||
self.alpha = ts.alpha
|
||||
self.additive = ts.additive
|
||||
self.rotate = ts.rotate
|
||||
self.rotate_pad = ts.rotate_pad
|
||||
self.transform_anchor = ts.transform_anchor
|
||||
@@ -196,6 +199,7 @@ class TransformState(renpy.object.Object):
|
||||
rv[prop] = (old_value, new_value)
|
||||
|
||||
diff2("alpha", newts.alpha, self.alpha)
|
||||
diff2("additive", newts.additive, self.additive)
|
||||
diff2("rotate", newts.rotate, self.rotate)
|
||||
diff2("rotate_pad", newts.rotate_pad, self.rotate_pad)
|
||||
diff2("transform_anchor", newts.transform_anchor, self.transform_anchor)
|
||||
@@ -380,6 +384,7 @@ class Transform(Container):
|
||||
|
||||
# Proxying things over to our state.
|
||||
alpha = Proxy("alpha")
|
||||
additive = Proxy("additive")
|
||||
rotate = Proxy("rotate")
|
||||
rotate_pad = Proxy("rotate_pad")
|
||||
transform_anchor = Proxy("rotate_pad")
|
||||
@@ -514,7 +519,7 @@ class Transform(Container):
|
||||
raise Exception("Unknown transform property prefix: %r" % prefix)
|
||||
|
||||
if prop not in renpy.atl.PROPERTIES:
|
||||
raise Exception("Unknown transform property: %r")
|
||||
raise Exception("Unknown transform property: %r" % prop)
|
||||
|
||||
self.arguments[prefix][prop] = v
|
||||
|
||||
|
||||
@@ -191,8 +191,6 @@ def OldMoveTransition(delay, old_widget=None, new_widget=None, factory=None, ent
|
||||
# for each layer.
|
||||
if new.layers:
|
||||
|
||||
assert old.layers
|
||||
|
||||
rv = renpy.display.layout.MultiBox(layout='fixed')
|
||||
rv.layers = { }
|
||||
|
||||
@@ -502,8 +500,6 @@ def MoveTransition(delay, old_widget=None, new_widget=None, enter=None, leave=No
|
||||
# for each layer.
|
||||
if new.layers:
|
||||
|
||||
assert old.layers
|
||||
|
||||
rv = renpy.display.layout.MultiBox(layout='fixed')
|
||||
|
||||
for layer in renpy.config.layers:
|
||||
|
||||
@@ -282,7 +282,7 @@ class SpriteManager(renpy.display.core.Displayable):
|
||||
cst = st - cache.st
|
||||
|
||||
cache.render = r = render(cache.child, width, height, cst, cst)
|
||||
cache.fast = (r.operation == BLIT) and (r.forward is None) and (r.alpha == 1.0)
|
||||
cache.fast = (r.operation == BLIT) and (r.forward is None) and (r.alpha == 1.0) and (r.over == 1.0)
|
||||
rv.depends_on(r)
|
||||
|
||||
caches.append(cache)
|
||||
|
||||
@@ -24,6 +24,7 @@ cdef class Render:
|
||||
|
||||
cdef public Matrix2D forward, reverse
|
||||
cdef public double alpha
|
||||
cdef public double over
|
||||
|
||||
cdef public list focuses
|
||||
cdef public list pass_focuses
|
||||
|
||||
@@ -508,6 +508,10 @@ cdef class Render:
|
||||
|
||||
# This is used to adjust the alpha of children of this render.
|
||||
self.alpha = 1
|
||||
|
||||
# The over blending factor. When this is 1.0, we get fully additive
|
||||
# blending. When set to 0.0, we get additive blending.
|
||||
self.over = 1.0
|
||||
|
||||
# A list of focus regions in this displayable.
|
||||
self.focuses = None
|
||||
|
||||
@@ -478,10 +478,10 @@ def draw(dest, clip, what, xo, yo, screen):
|
||||
dest = dest.subsurface((x, y, width, height))
|
||||
|
||||
# Deal with alpha and transforms by passing them off to draw_transformed.
|
||||
if what.alpha != 1 or (what.forward is not None and what.forward is not IDENTITY):
|
||||
if what.alpha != 1 or what.over != 1.0 or (what.forward is not None and what.forward is not IDENTITY):
|
||||
for child, cxo, cyo, _focus, _main in what.visible_children:
|
||||
draw_transformed(dest, clip, child, xo + cxo, yo + cyo,
|
||||
what.alpha, what.forward, what.reverse)
|
||||
what.alpha * what.over, what.forward, what.reverse)
|
||||
return
|
||||
|
||||
for child, cxo, cyo, _focus, _main in what.visible_children:
|
||||
@@ -629,7 +629,7 @@ def draw_transformed(dest, clip, what, xo, yo, alpha, forward, reverse):
|
||||
child_forward = forward
|
||||
child_reverse = reverse
|
||||
|
||||
draw_transformed(dest, clip, child, xo + cxo, yo + cyo, alpha * what.alpha, child_forward, child_reverse)
|
||||
draw_transformed(dest, clip, child, xo + cxo, yo + cyo, alpha * what.alpha * what.over, child_forward, child_reverse)
|
||||
|
||||
|
||||
|
||||
@@ -695,7 +695,7 @@ class SWDraw(object):
|
||||
self.fullscreen_surface = None
|
||||
|
||||
# Info.
|
||||
self.info = { "renderer" : "sw", "resizable" : False }
|
||||
self.info = { "renderer" : "sw", "resizable" : False, "additive" : False }
|
||||
|
||||
pygame.display.init()
|
||||
renpy.display.interface.post_init()
|
||||
|
||||
@@ -127,6 +127,10 @@ def launch_editor(filenames, line=1, transient=False):
|
||||
Causes the editor to be launched.
|
||||
"""
|
||||
|
||||
# On android, we will never be able to launch the editor.
|
||||
if renpy.android:
|
||||
return True
|
||||
|
||||
if editor is None:
|
||||
init()
|
||||
|
||||
|
||||
+6
-2
@@ -507,8 +507,12 @@ def run_context(top):
|
||||
label = None
|
||||
|
||||
context.run()
|
||||
|
||||
rv = renpy.store._return
|
||||
|
||||
context.pop_all_dynamic()
|
||||
break
|
||||
|
||||
return rv
|
||||
|
||||
except renpy.game.RestartContext as e:
|
||||
|
||||
@@ -532,5 +536,5 @@ def run_context(top):
|
||||
context.pop_all_dynamic()
|
||||
raise
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+4
-1
@@ -1668,9 +1668,12 @@ def get_renderer_info():
|
||||
One of ``"gl"`` or ``"sw"``, corresponding to the OpenGL and
|
||||
software renderers, respectively.
|
||||
|
||||
``"resizable``
|
||||
``"resizable"``
|
||||
True if and only if the window is resizable.
|
||||
|
||||
``"additive"``
|
||||
True if and only if the renderer supports additive blending.
|
||||
|
||||
Other, renderer-specific, keys may also exist. The dictionary should
|
||||
be treated as immutable. This should only be called once the display
|
||||
has been started (that is, after the init code is finished).
|
||||
|
||||
+1
-5
@@ -366,11 +366,7 @@ def call_in_new_context(label, *args, **kwargs):
|
||||
try:
|
||||
|
||||
context.goto_label(label)
|
||||
renpy.execution.run_context(False)
|
||||
|
||||
rv = renpy.store._return #@UndefinedVariable
|
||||
|
||||
return rv
|
||||
return renpy.execution.run_context(False)
|
||||
|
||||
except renpy.game.JumpOutException, e:
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ cdef class GLDraw:
|
||||
cdef bint fast_dissolve
|
||||
cdef bint always_opaque
|
||||
cdef bint allow_fixed
|
||||
cdef tuple default_clip
|
||||
|
||||
cdef public tuple clip_rtt_box
|
||||
|
||||
@@ -43,6 +44,7 @@ cdef class GLDraw:
|
||||
double xo,
|
||||
double yo,
|
||||
double alpha,
|
||||
double over,
|
||||
render.Matrix2D reverse)
|
||||
|
||||
cdef class Environ:
|
||||
|
||||
+39
-27
@@ -111,7 +111,7 @@ cdef class GLDraw:
|
||||
self.redraw_period = .2
|
||||
|
||||
# Info.
|
||||
self.info = { "resizable" : True }
|
||||
self.info = { "resizable" : True, "additive" : True }
|
||||
|
||||
if not ANGLE:
|
||||
self.info["renderer"] = "gl"
|
||||
@@ -206,19 +206,21 @@ cdef class GLDraw:
|
||||
# Handle swap control.
|
||||
vsync = int(os.environ.get("RENPY_GL_VSYNC", "1"))
|
||||
|
||||
# Switch the
|
||||
IF not ANGLE:
|
||||
if ANGLE:
|
||||
opengl = 0
|
||||
resizable = 0
|
||||
elif renpy.android:
|
||||
opengl = pygame.OPENGL
|
||||
resizable = 0
|
||||
else:
|
||||
opengl = pygame.OPENGL
|
||||
pygame.display.gl_set_attribute(pygame.GL_SWAP_CONTROL, vsync)
|
||||
pygame.display.gl_set_attribute(pygame.GL_ALPHA_SIZE, 8)
|
||||
ELSE:
|
||||
opengl = 0
|
||||
# EGL automatically handles vsync for us.
|
||||
|
||||
if renpy.config.gl_resize:
|
||||
resizable = pygame.RESIZABLE
|
||||
else:
|
||||
resizable = 0
|
||||
if renpy.config.gl_resize:
|
||||
resizable = pygame.RESIZABLE
|
||||
else:
|
||||
resizable = 0
|
||||
|
||||
try:
|
||||
if fullscreen:
|
||||
@@ -382,12 +384,13 @@ cdef class GLDraw:
|
||||
return False
|
||||
|
||||
if ANGLE:
|
||||
gltexture.use_angle()
|
||||
elif version.startswith("OpenGL ES"):
|
||||
gltexture.use_gles()
|
||||
|
||||
elif renpy.android:
|
||||
self.redraw_period = 1.0
|
||||
self.always_opaque = True
|
||||
|
||||
gltexture.use_gles()
|
||||
|
||||
else:
|
||||
gltexture.use_gl()
|
||||
|
||||
@@ -433,7 +436,7 @@ cdef class GLDraw:
|
||||
|
||||
# Pick a texture environment subsystem.
|
||||
|
||||
if ANGLE or (allow_shader and use_subsystem(
|
||||
if ANGLE or renpy.android or (allow_shader and use_subsystem(
|
||||
glenviron_shader,
|
||||
"RENPY_GL_ENVIRON",
|
||||
"shader",
|
||||
@@ -646,17 +649,18 @@ cdef class GLDraw:
|
||||
glClearColor(0.0, 0.0, 0.0, 1.0)
|
||||
glClear(GL_COLOR_BUFFER_BIT)
|
||||
|
||||
clip = (0, 0, self.virtual_size[0], self.virtual_size[1])
|
||||
self.default_clip = (0, 0, self.virtual_size[0], self.virtual_size[1])
|
||||
clip = self.default_clip
|
||||
|
||||
self.upscale_factor = 1.0 * self.physical_size[0] / self.virtual_size[0]
|
||||
|
||||
if renpy.audio.music.get_playing("movie") and renpy.display.video.fullscreen:
|
||||
surf = renpy.display.video.render_movie(self.virtual_size[0], self.virtual_size[1])
|
||||
if surf is not None:
|
||||
self.draw_transformed(surf, clip, 0, 0, 1.0, reverse)
|
||||
self.draw_transformed(surf, clip, 0, 0, 1.0, 1.0, reverse)
|
||||
|
||||
else:
|
||||
self.draw_transformed(surftree, clip, 0, 0, 1.0, reverse)
|
||||
self.draw_transformed(surftree, clip, 0, 0, 1.0, 1.0, reverse)
|
||||
|
||||
if flip:
|
||||
|
||||
@@ -733,6 +737,7 @@ cdef class GLDraw:
|
||||
double xo,
|
||||
double yo,
|
||||
double alpha,
|
||||
double over,
|
||||
render.Matrix2D reverse):
|
||||
|
||||
cdef render.Render rend
|
||||
@@ -751,6 +756,7 @@ cdef class GLDraw:
|
||||
yo,
|
||||
reverse,
|
||||
alpha,
|
||||
over,
|
||||
self.environ,
|
||||
False)
|
||||
|
||||
@@ -759,7 +765,7 @@ cdef class GLDraw:
|
||||
if isinstance(what, pygame.Surface):
|
||||
|
||||
tex = self.load_texture(what)
|
||||
self.draw_transformed(tex, clip, xo, yo, alpha, reverse)
|
||||
self.draw_transformed(tex, clip, xo, yo, alpha, over, reverse)
|
||||
return 0
|
||||
|
||||
raise Exception("Unknown drawing type. " + repr(what))
|
||||
@@ -777,10 +783,10 @@ cdef class GLDraw:
|
||||
# of dissolve on Ren'Py proper.
|
||||
|
||||
self.draw_transformed(rend.children[0][0],
|
||||
clip, xo, yo, alpha, reverse)
|
||||
clip, xo, yo, alpha, over, reverse)
|
||||
|
||||
self.draw_transformed(rend.children[1][0],
|
||||
clip, xo, yo, alpha * what.operation_complete, reverse)
|
||||
clip, xo, yo, alpha * what.operation_complete, over, reverse)
|
||||
|
||||
else:
|
||||
|
||||
@@ -793,6 +799,7 @@ cdef class GLDraw:
|
||||
yo,
|
||||
reverse,
|
||||
alpha,
|
||||
over,
|
||||
rend.operation_complete,
|
||||
self.environ)
|
||||
|
||||
@@ -810,6 +817,7 @@ cdef class GLDraw:
|
||||
yo,
|
||||
reverse,
|
||||
alpha,
|
||||
over,
|
||||
rend.operation_complete,
|
||||
rend.operation_parameter,
|
||||
self.environ)
|
||||
@@ -835,6 +843,7 @@ cdef class GLDraw:
|
||||
yo,
|
||||
reverse,
|
||||
alpha,
|
||||
over,
|
||||
self.environ,
|
||||
True)
|
||||
|
||||
@@ -847,7 +856,7 @@ cdef class GLDraw:
|
||||
# Non-aligned clipping uses RTT.
|
||||
if reverse.ydx != 0 or reverse.xdy != 0:
|
||||
tex = what.render_to_texture(True)
|
||||
self.draw_transformed(tex, clip, xo, yo, alpha, reverse)
|
||||
self.draw_transformed(tex, clip, xo, yo, alpha, over, reverse)
|
||||
return 0
|
||||
|
||||
minx, miny, maxx, maxy = clip
|
||||
@@ -864,7 +873,8 @@ cdef class GLDraw:
|
||||
clip = (minx, miny, maxx, maxy)
|
||||
|
||||
alpha = alpha * rend.alpha
|
||||
|
||||
over = over * rend.over
|
||||
|
||||
# If our alpha has hit 0, don't do anything.
|
||||
if alpha <= 0.003: # (1 / 256)
|
||||
return 0
|
||||
@@ -878,7 +888,7 @@ cdef class GLDraw:
|
||||
tcxo = reverse.xdx * cxo + reverse.xdy * cyo
|
||||
tcyo = reverse.ydx * cxo + reverse.ydy * cyo
|
||||
|
||||
self.draw_transformed(child, clip, xo + tcxo, yo + tcyo, alpha, child_reverse)
|
||||
self.draw_transformed(child, clip, xo + tcxo, yo + tcyo, alpha, over, child_reverse)
|
||||
|
||||
return 0
|
||||
|
||||
@@ -899,9 +909,10 @@ cdef class GLDraw:
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT)
|
||||
|
||||
clip = (0, 0, what.width, what.height)
|
||||
self.default_clip = (0, 0, what.width, what.height)
|
||||
clip = self.default_clip
|
||||
|
||||
self.draw_transformed(what, clip, 0, 0, 1.0, reverse)
|
||||
self.draw_transformed(what, clip, 0, 0, 1.0, 1.0, reverse)
|
||||
|
||||
if isinstance(what, render.Render):
|
||||
what.is_opaque()
|
||||
@@ -939,7 +950,7 @@ cdef class GLDraw:
|
||||
|
||||
clip = (0, 0, 1, 1)
|
||||
|
||||
self.draw_transformed(what, clip, 0, 0, 1.0, reverse)
|
||||
self.draw_transformed(what, clip, 0, 0, 1.0, 1.0, reverse)
|
||||
|
||||
cdef unsigned char pixel[4]
|
||||
|
||||
@@ -978,7 +989,7 @@ cdef class GLDraw:
|
||||
|
||||
clip = (0, 0, width, height)
|
||||
|
||||
draw.draw_transformed(what, clip, 0, 0, 1.0, reverse)
|
||||
draw.draw_transformed(what, clip, 0, 0, 1.0, 1.0, reverse)
|
||||
|
||||
if isinstance(what, render.Render):
|
||||
what.is_opaque()
|
||||
@@ -1063,6 +1074,7 @@ cdef class GLDraw:
|
||||
y,
|
||||
IDENTITY,
|
||||
1.0,
|
||||
1.0,
|
||||
self.environ,
|
||||
False)
|
||||
|
||||
|
||||
@@ -121,6 +121,27 @@ varying vec2 pos;
|
||||
uniform vec2 clip0;
|
||||
uniform vec2 clip1;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 color0 = texture2D(tex0, TexCoord0.st);
|
||||
gl_FragColor = color0 * Color;
|
||||
}
|
||||
"""
|
||||
|
||||
BLIT_CLIP_SHADER = """
|
||||
#ifdef GL_ES
|
||||
precision highp float;
|
||||
#endif
|
||||
|
||||
uniform vec4 Color;
|
||||
uniform sampler2D tex0;
|
||||
|
||||
varying vec2 TexCoord0;
|
||||
|
||||
varying vec2 pos;
|
||||
uniform vec2 clip0;
|
||||
uniform vec2 clip1;
|
||||
|
||||
void main()
|
||||
{
|
||||
if (pos.x < clip0.x || pos.y < clip0.y || pos.x >= clip1.x || pos.y >= clip1.y) {
|
||||
@@ -149,6 +170,33 @@ varying vec2 pos;
|
||||
uniform vec2 clip0;
|
||||
uniform vec2 clip1;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 color0 = texture2D(tex0, TexCoord0.st);
|
||||
vec4 color1 = texture2D(tex1, TexCoord1.st);
|
||||
|
||||
gl_FragColor = mix(color0, color1, done) * Color;
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
BLEND_CLIP_SHADER = """
|
||||
#ifdef GL_ES
|
||||
precision highp float;
|
||||
#endif
|
||||
|
||||
uniform vec4 Color;
|
||||
uniform sampler2D tex0;
|
||||
uniform sampler2D tex1;
|
||||
uniform float done;
|
||||
|
||||
varying vec2 TexCoord0;
|
||||
varying vec2 TexCoord1;
|
||||
|
||||
varying vec2 pos;
|
||||
uniform vec2 clip0;
|
||||
uniform vec2 clip1;
|
||||
|
||||
void main()
|
||||
{
|
||||
if (pos.x < clip0.x || pos.y < clip0.y || pos.x >= clip1.x || pos.y >= clip1.y) {
|
||||
@@ -182,6 +230,38 @@ varying vec2 pos;
|
||||
uniform vec2 clip0;
|
||||
uniform vec2 clip1;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 color0 = texture2D(tex0, TexCoord0.st);
|
||||
vec4 color1 = texture2D(tex1, TexCoord1.st);
|
||||
vec4 color2 = texture2D(tex2, TexCoord2.st);
|
||||
|
||||
float a = clamp((color0.a + offset) * multiplier, 0.0, 1.0);
|
||||
|
||||
gl_FragColor = mix(color1, color2, a) * Color;
|
||||
}
|
||||
"""
|
||||
|
||||
IMAGEBLEND_CLIP_SHADER = """
|
||||
#ifdef GL_ES
|
||||
precision highp float;
|
||||
#endif
|
||||
|
||||
uniform vec4 Color;
|
||||
uniform sampler2D tex0;
|
||||
uniform sampler2D tex1;
|
||||
uniform sampler2D tex2;
|
||||
uniform float offset;
|
||||
uniform float multiplier;
|
||||
|
||||
varying vec2 TexCoord0;
|
||||
varying vec2 TexCoord1;
|
||||
varying vec2 TexCoord2;
|
||||
|
||||
varying vec2 pos;
|
||||
uniform vec2 clip0;
|
||||
uniform vec2 clip1;
|
||||
|
||||
void main()
|
||||
{
|
||||
if (pos.x < clip0.x || pos.y < clip0.y || pos.x >= clip1.x || pos.y >= clip1.y) {
|
||||
@@ -200,6 +280,7 @@ void main()
|
||||
|
||||
|
||||
|
||||
|
||||
def check_status(shader, handle, type):
|
||||
"""
|
||||
Checks the status of a shader or program. If it fails, then an
|
||||
@@ -351,6 +432,11 @@ cdef class ShaderEnviron(Environ):
|
||||
cdef Program blend_program
|
||||
cdef Program imageblend_program
|
||||
|
||||
cdef Program blit_clip_program
|
||||
cdef Program blend_clip_program
|
||||
cdef Program imageblend_clip_program
|
||||
|
||||
cdef bint clipping
|
||||
cdef double clip_x0
|
||||
cdef double clip_y0
|
||||
cdef double clip_x1
|
||||
@@ -361,11 +447,17 @@ cdef class ShaderEnviron(Environ):
|
||||
cdef int viewport_w
|
||||
cdef int viewport_h
|
||||
|
||||
|
||||
def init(self):
|
||||
|
||||
self.blit_program = Program(VERTEX_SHADER1, BLIT_SHADER)
|
||||
self.blit_clip_program = Program(VERTEX_SHADER1, BLIT_CLIP_SHADER)
|
||||
|
||||
self.blend_program = Program(VERTEX_SHADER2, BLEND_SHADER)
|
||||
self.blend_clip_program = Program(VERTEX_SHADER2, BLEND_CLIP_SHADER)
|
||||
|
||||
self.imageblend_program = Program(VERTEX_SHADER3, IMAGEBLEND_SHADER)
|
||||
self.imageblend_clip_program = Program(VERTEX_SHADER3, IMAGEBLEND_CLIP_SHADER)
|
||||
|
||||
# The current program.
|
||||
self.program = None
|
||||
@@ -392,19 +484,27 @@ cdef class ShaderEnviron(Environ):
|
||||
|
||||
glUseProgramObjectARB(program.program)
|
||||
glUniformMatrix4fvARB(program.Projection, 1, GL_FALSE, self.projection)
|
||||
glUniform2fARB(program.clip0, self.clip_x0, self.clip_y0)
|
||||
glUniform2fARB(program.clip1, self.clip_x1, self.clip_y1)
|
||||
|
||||
if self.clipping:
|
||||
glUniform2fARB(program.clip0, self.clip_x0, self.clip_y0)
|
||||
glUniform2fARB(program.clip1, self.clip_x1, self.clip_y1)
|
||||
|
||||
cdef void blit(self):
|
||||
|
||||
program = self.blit_program
|
||||
if self.clipping:
|
||||
program = self.blit_clip_program
|
||||
else:
|
||||
program = self.blit_program
|
||||
|
||||
if self.program is not program:
|
||||
self.activate(program)
|
||||
glUniform1iARB(program.tex0, 0)
|
||||
|
||||
cdef void blend(self, double fraction):
|
||||
program = self.blend_program
|
||||
if self.clipping:
|
||||
program = self.blend_clip_program
|
||||
else:
|
||||
program = self.blend_program
|
||||
|
||||
if self.program is not program:
|
||||
self.activate(program)
|
||||
@@ -415,7 +515,10 @@ cdef class ShaderEnviron(Environ):
|
||||
|
||||
cdef void imageblend(self, double fraction, int ramp):
|
||||
|
||||
program = self.imageblend_program
|
||||
if self.clipping:
|
||||
program = self.imageblend_clip_program
|
||||
else:
|
||||
program = self.imageblend_program
|
||||
|
||||
if self.program is not program:
|
||||
self.activate(program)
|
||||
@@ -508,10 +611,15 @@ cdef class ShaderEnviron(Environ):
|
||||
cdef int cx, cy, cw, ch
|
||||
cdef int psw, psh
|
||||
|
||||
if clip_box == draw.default_clip:
|
||||
self.unset_clip(draw)
|
||||
return
|
||||
|
||||
minx, miny, maxx, maxy = clip_box
|
||||
psw, psh = draw.physical_size
|
||||
|
||||
# The clipping box.
|
||||
# The clipping box.
|
||||
self.clipping = True
|
||||
self.clip_x0 = minx
|
||||
self.clip_y0 = miny
|
||||
self.clip_x1 = maxx
|
||||
@@ -566,7 +674,8 @@ cdef class ShaderEnviron(Environ):
|
||||
cdef void unset_clip(self, GLDraw draw):
|
||||
|
||||
glDisable(GL_SCISSOR_TEST)
|
||||
|
||||
|
||||
self.clipping = False
|
||||
self.clip_x0 = 0
|
||||
self.clip_y0 = 0
|
||||
self.clip_x1 = 65535
|
||||
|
||||
@@ -42,6 +42,7 @@ cpdef blit(
|
||||
double sy,
|
||||
render.Matrix2D transform,
|
||||
double alpha,
|
||||
double over,
|
||||
Environ environ,
|
||||
bint nearest)
|
||||
|
||||
@@ -52,6 +53,7 @@ cpdef blend(
|
||||
double sy,
|
||||
render.Matrix2D transform,
|
||||
double alpha,
|
||||
double over,
|
||||
double fraction,
|
||||
Environ environ)
|
||||
|
||||
@@ -63,6 +65,7 @@ cpdef imageblend(
|
||||
double sy,
|
||||
render.Matrix2D transform,
|
||||
double alpha,
|
||||
double over,
|
||||
double fraction,
|
||||
int ramp,
|
||||
Environ environ)
|
||||
|
||||
+16
-24
@@ -52,7 +52,7 @@ cdef GLenum rtt_format = GL_RGBA
|
||||
cdef GLenum rtt_internalformat = GL_RGBA
|
||||
cdef GLenum rtt_type = GL_UNSIGNED_BYTE
|
||||
|
||||
def use_angle():
|
||||
def use_gles():
|
||||
global tex_format
|
||||
global tex_internalformat
|
||||
global tex_type
|
||||
@@ -68,22 +68,6 @@ def use_angle():
|
||||
rtt_internalformat = GL_RGBA
|
||||
rtt_type = GL_UNSIGNED_BYTE
|
||||
|
||||
def use_gles():
|
||||
global tex_format
|
||||
global tex_internalformat
|
||||
global tex_type
|
||||
global rtt_format
|
||||
global rtt_internalformat
|
||||
global rtt_type
|
||||
|
||||
tex_format = GL_RGBA
|
||||
tex_internalformat = GL_RGBA
|
||||
tex_type = GL_UNSIGNED_BYTE
|
||||
|
||||
rtt_format = GL_RGB
|
||||
rtt_internalformat = GL_RGB
|
||||
rtt_type = GL_UNSIGNED_BYTE
|
||||
|
||||
def use_gl():
|
||||
global tex_format
|
||||
global tex_internalformat
|
||||
@@ -889,7 +873,7 @@ def align_axes(*args):
|
||||
return rv
|
||||
|
||||
|
||||
cpdef blit(TextureGrid tg, double sx, double sy, render.Matrix2D transform, double alpha, Environ environ, bint nearest):
|
||||
cpdef blit(TextureGrid tg, double sx, double sy, render.Matrix2D transform, double alpha, double over, Environ environ, bint nearest):
|
||||
"""
|
||||
This draws texgrid `tg` to the screen. `sx` and `sy` are offsets from
|
||||
the upper-left corner of the screen.
|
||||
@@ -898,6 +882,8 @@ cpdef blit(TextureGrid tg, double sx, double sy, render.Matrix2D transform, doub
|
||||
texgrid coordinates to screen coordinates.
|
||||
|
||||
`alpha` is the alpha multiplier applied, from 0.0 to 1.0.
|
||||
|
||||
`over` is the over blending factor.
|
||||
"""
|
||||
|
||||
cdef int x, y
|
||||
@@ -906,7 +892,7 @@ cpdef blit(TextureGrid tg, double sx, double sy, render.Matrix2D transform, doub
|
||||
tg.make_ready(nearest)
|
||||
|
||||
environ.blit()
|
||||
environ.set_color(alpha, alpha, alpha, alpha)
|
||||
environ.set_color(alpha, alpha, alpha, over * alpha)
|
||||
|
||||
y = 0
|
||||
|
||||
@@ -932,7 +918,7 @@ cpdef blit(TextureGrid tg, double sx, double sy, render.Matrix2D transform, doub
|
||||
|
||||
y += texh
|
||||
|
||||
cpdef blend(TextureGrid tg0, TextureGrid tg1, double sx, double sy, render.Matrix2D transform, double alpha, double fraction, Environ environ):
|
||||
cpdef blend(TextureGrid tg0, TextureGrid tg1, double sx, double sy, render.Matrix2D transform, double alpha, double over, double fraction, Environ environ):
|
||||
"""
|
||||
Blends two textures to the screen.
|
||||
|
||||
@@ -945,6 +931,8 @@ cpdef blend(TextureGrid tg0, TextureGrid tg1, double sx, double sy, render.Matri
|
||||
|
||||
`alpha` is the alpha multiplier applied, from 0.0 to 1.0.
|
||||
|
||||
`over` is the over blending factor.
|
||||
|
||||
`fraction` is the fraction of the second texture to show.
|
||||
"""
|
||||
|
||||
@@ -952,7 +940,7 @@ cpdef blend(TextureGrid tg0, TextureGrid tg1, double sx, double sy, render.Matri
|
||||
tg1.make_ready(False)
|
||||
|
||||
environ.blend(fraction)
|
||||
environ.set_color(alpha, alpha, alpha, alpha)
|
||||
environ.set_color(alpha, alpha, alpha, over * alpha)
|
||||
|
||||
y = 0
|
||||
|
||||
@@ -985,8 +973,9 @@ cpdef blend(TextureGrid tg0, TextureGrid tg1, double sx, double sy, render.Matri
|
||||
x += t0w
|
||||
|
||||
y += t0h
|
||||
|
||||
|
||||
cpdef imageblend(TextureGrid tg0, TextureGrid tg1, TextureGrid tg2, double sx, double sy, render.Matrix2D transform, double alpha, double fraction, int ramp, Environ environ):
|
||||
cpdef imageblend(TextureGrid tg0, TextureGrid tg1, TextureGrid tg2, double sx, double sy, render.Matrix2D transform, double alpha, double over, double fraction, int ramp, Environ environ):
|
||||
"""
|
||||
This uses texture 0 to control the blending of tetures 1 and 2 to
|
||||
the screen.
|
||||
@@ -998,7 +987,10 @@ cpdef imageblend(TextureGrid tg0, TextureGrid tg1, TextureGrid tg2, double sx, d
|
||||
`transform` is the transform to apply to the texgrid, when going from
|
||||
texgrid coordinates to screen coordinates.
|
||||
|
||||
`alpha` is the alpha multiplier applied, from 0.0 to 1.0.
|
||||
`over` is the over blending factor.
|
||||
|
||||
`additive` is the additive blending factor, which is 1.0 for fully additive,
|
||||
and 0.0 for fully over blending.
|
||||
|
||||
`fraction` is the fraction of the second texture to show.
|
||||
|
||||
@@ -1011,7 +1003,7 @@ cpdef imageblend(TextureGrid tg0, TextureGrid tg1, TextureGrid tg2, double sx, d
|
||||
tg2.make_ready(False)
|
||||
|
||||
environ.imageblend(fraction, ramp)
|
||||
environ.set_color(alpha, alpha, alpha, alpha)
|
||||
environ.set_color(alpha, alpha, alpha, over * alpha)
|
||||
|
||||
y = 0
|
||||
|
||||
|
||||
+21
-4
@@ -26,12 +26,29 @@ from cStringIO import StringIO
|
||||
import sys
|
||||
import types
|
||||
|
||||
# Ensure the utf-8 codec is loaded, to prevent recursion when we use it
|
||||
# to look up filenames.
|
||||
u"".encode("utf-8")
|
||||
|
||||
try:
|
||||
import android.apk
|
||||
apks = [
|
||||
android.apk.APK(prefix='assets/x-game/'),
|
||||
android.apk.APK(prefix='assets/x-common/'),
|
||||
]
|
||||
|
||||
expansion = os.environ.get("ANDROID_EXPANSION", None)
|
||||
if expansion is not None:
|
||||
print "Using expansion file", expansion
|
||||
|
||||
apks = [
|
||||
android.apk.APK(apk=expansion, prefix='assets/x-game/'),
|
||||
android.apk.APK(apk=expansion, prefix='assets/x-common/'),
|
||||
]
|
||||
else:
|
||||
print "Not using expansion file."
|
||||
|
||||
apks = [
|
||||
android.apk.APK(prefix='assets/x-game/'),
|
||||
android.apk.APK(prefix='assets/x-common/'),
|
||||
]
|
||||
|
||||
except ImportError:
|
||||
apks = [ ]
|
||||
|
||||
|
||||
+1
-1
@@ -73,7 +73,7 @@ class LogFile(object):
|
||||
return False
|
||||
|
||||
try:
|
||||
base = os.environ.get("RENPY_LOG_BASE", renpy.config.basedir)
|
||||
base = os.environ.get("RENPY_LOG_BASE", renpy.config.logdir)
|
||||
fn = os.path.join(base, self.name + ".txt")
|
||||
|
||||
altfn = os.path.join(tempfile.gettempdir(), "renpy-" + self.name + ".txt")
|
||||
|
||||
@@ -154,6 +154,10 @@ def main():
|
||||
renpy.config.commondir = commondir
|
||||
else:
|
||||
renpy.config.commondir = None
|
||||
|
||||
if renpy.android:
|
||||
renpy.config.searchpath = [ ]
|
||||
renpy.config.commondir = None
|
||||
|
||||
# Load Ren'Py extensions.
|
||||
for dir in renpy.config.searchpath: #@ReservedAssignment
|
||||
|
||||
+2
-3
@@ -943,9 +943,6 @@ class Lexer(object):
|
||||
|
||||
for _fn, ln, text, subblock in block:
|
||||
|
||||
if o.line > ln:
|
||||
assert False
|
||||
|
||||
while o.line < ln:
|
||||
rv.append(indent + '\n')
|
||||
o.line += 1
|
||||
@@ -1272,6 +1269,7 @@ def parse_parameters(l):
|
||||
names.add(name)
|
||||
|
||||
if l.match(r'='):
|
||||
l.skip_whitespace()
|
||||
default = l.delimited_python("),")
|
||||
else:
|
||||
default = None
|
||||
@@ -1329,6 +1327,7 @@ def parse_arguments(l):
|
||||
l.revert(state)
|
||||
name = None
|
||||
|
||||
l.skip_whitespace()
|
||||
arguments.append((name, l.delimited_python("),")))
|
||||
|
||||
if l.match(r'\)'):
|
||||
|
||||
+17
-3
@@ -107,9 +107,23 @@ def expand_anchor(v):
|
||||
"""
|
||||
Turns an anchor into a number.
|
||||
"""
|
||||
|
||||
return anchors.get(v, v)
|
||||
|
||||
|
||||
try:
|
||||
return anchors.get(v, v)
|
||||
except:
|
||||
# This fixes some bugs in very old Ren'Pys.
|
||||
|
||||
for n in anchors:
|
||||
o = getattr(renpy.store, n, None)
|
||||
if o is None:
|
||||
continue
|
||||
|
||||
if v is o:
|
||||
return anchors[n]
|
||||
|
||||
raise
|
||||
|
||||
|
||||
|
||||
# A map of properties that we know about. The properties may take a
|
||||
# function that is called to convert the argument to something more
|
||||
|
||||
@@ -314,7 +314,7 @@ cdef class FTFont:
|
||||
|
||||
rv.index = index
|
||||
|
||||
error = FT_Load_Glyph(face, index, 0)
|
||||
error = FT_Load_Glyph(face, index, FT_LOAD_FORCE_AUTOHINT)
|
||||
if error:
|
||||
raise FreetypeError(error)
|
||||
|
||||
|
||||
@@ -315,7 +315,7 @@ class StringTranslator(object):
|
||||
new = self.translations.get(notags, None)
|
||||
|
||||
if new is not None:
|
||||
return True
|
||||
return new
|
||||
|
||||
return old
|
||||
|
||||
|
||||
@@ -25,5 +25,5 @@ fi
|
||||
if [ "$1" = "--build" ] ; then
|
||||
echo "Ren'Py build complete."
|
||||
else
|
||||
exec ./renpy.py "$@"
|
||||
exec python -OO ./renpy.py "$@"
|
||||
fi
|
||||
|
||||
@@ -447,3 +447,29 @@ And install the packages. Then, try building your game again.
|
||||
|
||||
http://lemmasoft.renai.us/forums/viewtopic.php?f=32&t=13987&hilit=rapt
|
||||
|
||||
Expansion APKs
|
||||
--------------
|
||||
|
||||
|PGS4A| optionally supports the use of expansion APKs when used on a
|
||||
device supporting Google Play. Please see:
|
||||
|
||||
http://developer.android.com/google/play/expansion-files.html
|
||||
|
||||
For information about expansion APKs work. Right now, only the
|
||||
main expansion APK is supported, giving a 2GB limit.
|
||||
|
||||
.. ifconfig:: not is_renpy
|
||||
|
||||
When an android APK is created, all assets (from the assets
|
||||
directory) are placed in the expansion APK. The assets can be
|
||||
accessed through the :module:`android.assets` interface.
|
||||
|
||||
.. ifconfig:: is_renpy
|
||||
|
||||
When an APK is created, all game files will be placed in the
|
||||
expansion APK. Ren'Py will transparently use these files.
|
||||
|
||||
|PGS4A| will place the expansion APK on the device when installing
|
||||
the APK package on the device. In normal operation, Google Play will
|
||||
place the expansion APK on the device automatically.
|
||||
|
||||
|
||||
@@ -45,20 +45,8 @@ due to the Android software and hardware are:
|
||||
screen. When the user is not touching the screen, the virtual
|
||||
pointer will move to the upper-left corner of the screen.
|
||||
|
||||
* :func:`ImageDissolve`, :func:`AlphaDissolve`, and :func:`AlphaBlend`
|
||||
are not supported.
|
||||
|
||||
* Functions that render to a texture can only render an opaque
|
||||
texture. This means that the :func:`Dissolve` and :func:`Pixellate`
|
||||
transitions will only produce opaque output.
|
||||
|
||||
* The :propref:`focus_mask` property is not supported. It will be
|
||||
treated as if all pixels in the mask are opaque.
|
||||
|
||||
* Movie playback is not supported.
|
||||
|
||||
* Launching the web browser is not supported.
|
||||
|
||||
* Some python modules (including network communication) modules are
|
||||
not supported.
|
||||
|
||||
|
||||
@@ -751,6 +751,37 @@ both horizontal and vertical positions.
|
||||
|
||||
This controls the opacity of the displayable.
|
||||
|
||||
The alpha transform is applied to each image comprising the child of
|
||||
the transform independently. This can lead to unexpected results when
|
||||
the children overlap, such as as seeing a character through clothing.
|
||||
The :func:`Flatten` displayable can help with these problems.
|
||||
|
||||
.. transform-property:: additive
|
||||
|
||||
:type: float
|
||||
:default: 0.0
|
||||
|
||||
This controls how much additive blending Ren'Py performs. When 1.0,
|
||||
Ren'Py draws using the ADD operator. When 0.0, Ren'Py draws using
|
||||
the OVER operator.
|
||||
|
||||
Additive blending is performed on each child of the transform independently.
|
||||
|
||||
Fully additive blending doesn't alter the alpha channel of the destination,
|
||||
and additive images may not be visible if they're not drawn directly onto
|
||||
an opaque surface. (Complex operations, like viewport, :func:`Flatten`, :func:`Frame`,
|
||||
and certain transitions may cause problems with additive blending.)
|
||||
|
||||
.. warning::
|
||||
|
||||
Additive blending is only supported by hardware-based renderers, such
|
||||
as the OpenGL and DirectX/ANGLE renderers. The software renderer will
|
||||
draw additive images incorrectly.
|
||||
|
||||
Once the graphics system has started, ``renpy.get_renderer_info()["additive"]``
|
||||
will be true if additive blending is supported.
|
||||
|
||||
|
||||
.. transform-property:: around
|
||||
|
||||
:type: (position, position)
|
||||
|
||||
+121
-58
@@ -2,18 +2,82 @@
|
||||
Full Changelog
|
||||
==============
|
||||
|
||||
Ren'Py 6.15.6
|
||||
-------------
|
||||
|
||||
This release includes improvements for the Android platform:
|
||||
|
||||
* Assets are now read exclusively from the APK and expansion file.
|
||||
* Logs and tracebacks are placed on external storage.
|
||||
* Saves are placed on external storage, except when saves from
|
||||
older versions of Ren'Py exist.
|
||||
|
||||
The GL2 shaders Ren'Py uses have been simplified in the (usual) case
|
||||
where no clipping is occuring. This leads to a noticable speed
|
||||
improvement on Android, and potentially other platforms as well.
|
||||
|
||||
An issue with Drag-and-drop has been fixed. Thanks go to Kinsman
|
||||
for contributing this fixe.
|
||||
|
||||
The :func:`Skip` action now triggers the skip indicator. It also
|
||||
supports a new fast parameter, which causes skipping to the
|
||||
next menu.
|
||||
|
||||
This release includes various minor changes to improve compatibility
|
||||
with very old Ren'Py games. (It now runs the Ren'Py 5 demo.)
|
||||
|
||||
|
||||
Ren'Py 6.15.5
|
||||
-------------
|
||||
|
||||
This release adds two new features:
|
||||
|
||||
* The GL renderer now supports additive blending. This is enabled using the
|
||||
:tpref:`additive` transform property in an ATL transform or use of the
|
||||
:func:`Transform` class. Additive blending will not work if the software
|
||||
renderer is in use, and it's up to creators to deal with that issue.
|
||||
|
||||
* The new :func:`Flatten` displayable combines multiple textures into
|
||||
a single texture. This can be used to prevent incorrect behavior
|
||||
when a displayable containing multiple overlapping textures (like a
|
||||
:func:`LiveComposite` is shown with an :tpref:`alpha` between 0 and 1.
|
||||
|
||||
It also fixes the following issues:
|
||||
|
||||
* Whitespace is now skipped before default arguments, which previously
|
||||
caused parse errors in some cases.
|
||||
|
||||
* Ren'Py now sets the unix mode of files and directories in zip and tar
|
||||
files to 644 and 755 as appropriate. Prior versions of Ren'Py used
|
||||
666 and 777 as the permissions, which lead to a security problem
|
||||
when the file was unpacked by a tool that didn't respect the user's
|
||||
umask. (Info-zip had this problem.)
|
||||
|
||||
* Auto-hinting for fonts is now enabled by default. This restores font
|
||||
rendering compatibility with prior releases.
|
||||
|
||||
* Ren'Py now builds with and requires the current version of libav. It
|
||||
should also work with current versions of ffmpeg when libav is
|
||||
available.
|
||||
|
||||
* The version of SDL distributed with Ren'Py has been patched to
|
||||
prevent multiple windows from showing up in the Window menu
|
||||
when entering and leaving fullscreen mode.
|
||||
|
||||
|
||||
|
||||
Ren'Py 6.15.4
|
||||
-------------
|
||||
|
||||
This release fixes a compile problem that prevented Ren'Py 6.14.x and
|
||||
Ren'Py 6.15.0-3 from running on most 64-bit Linux systems.
|
||||
This release fixes a compile problem that prevented Ren'Py 6.14.x and Ren'Py
|
||||
6.15.0-3 from running on most 64-bit Linux systems.
|
||||
|
||||
Image prediction has become more fine-grained, and can take place
|
||||
while the screen is animating.
|
||||
Image prediction has become more fine-grained, and can take place while the
|
||||
screen is animating.
|
||||
|
||||
The new :var:`build.exclude_empty_directories` determines if empty
|
||||
directories are include or excluded from the distribution. It defaults
|
||||
to true, previously the default was platform-dependant.
|
||||
The new :var:`build.exclude_empty_directories` determines if empty directories
|
||||
are include or excluded from the distribution. It defaults to true,
|
||||
previously the default was platform-dependant.
|
||||
|
||||
|
||||
|
||||
@@ -33,21 +97,20 @@ combined at the translator's discretion. As most Ren'Py statements are
|
||||
allowed inside the new translation blocks, it's possible to use logic (like
|
||||
conditions) to tailor the translations to your language.
|
||||
|
||||
The launcher includes a new "Generate Translations" button, which - as part
|
||||
of a sanctioned translation where the full script is present - will generate
|
||||
The launcher includes a new "Generate Translations" button, which - as part of
|
||||
a sanctioned translation where the full script is present - will generate
|
||||
empty translation files for a new language.
|
||||
|
||||
Improved Japanese Support
|
||||
-------------------------
|
||||
|
||||
Ren'Py 6.15 includes multiple changes to better support the Japanese
|
||||
language.
|
||||
Ren'Py 6.15 includes multiple changes to better support the Japanese language.
|
||||
|
||||
* The tutorial game has been translated to Japanese, with the language
|
||||
being selectable from the preferences menu.
|
||||
* The tutorial game has been translated to Japanese, with the language being
|
||||
selectable from the preferences menu.
|
||||
|
||||
The tutorial was translated by Koichi Akabe.
|
||||
|
||||
|
||||
* Support for vertical writing has been added to Ren'Py. Consisting of the
|
||||
:propref:`vertical` style property for text, and the new
|
||||
:propref:`box_reverse` property on hboxes, this support makes it possible
|
||||
@@ -111,14 +174,13 @@ replay if one is in progress, and is ignored otherwise.
|
||||
Voice Improvements
|
||||
------------------
|
||||
|
||||
There have been several improvements to the voice playback system. The
|
||||
new :var:`config.voice_filename_format` variable makes it possible to
|
||||
use only part of the filename in a voice statement. The new voice_tag
|
||||
parameter to :func:`Character`, in conjunction with the
|
||||
:func:`SetVoiceMute` and :func:`ToggleVoiceMute` actions, makes it
|
||||
possible to selectively mute particular characters' voices. The new
|
||||
:func:`VoiceReplay` action makes it possible to replay the current
|
||||
voice.
|
||||
There have been several improvements to the voice playback system. The new
|
||||
:var:`config.voice_filename_format` variable makes it possible to use only
|
||||
part of the filename in a voice statement. The new voice_tag parameter to
|
||||
:func:`Character`, in conjunction with the :func:`SetVoiceMute` and
|
||||
:func:`ToggleVoiceMute` actions, makes it possible to selectively mute
|
||||
particular characters' voices. The new :func:`VoiceReplay` action makes it
|
||||
possible to replay the current voice.
|
||||
|
||||
Launcher Improvements
|
||||
---------------------
|
||||
@@ -139,44 +201,44 @@ There were a few launcher improvements in this release.
|
||||
Macintosh Changes
|
||||
-----------------
|
||||
|
||||
The Macintosh version of Ren'Py now requires a 64-bit capable processor,
|
||||
and Mac OS X 10.6 or newer.
|
||||
|
||||
The Macintosh version of Ren'Py now requires a 64-bit capable processor, and
|
||||
Mac OS X 10.6 or newer.
|
||||
|
||||
Packaging Improvements
|
||||
----------------------
|
||||
|
||||
The file layout of Ren'Py games has been somewhat altered. With the
|
||||
exception of small launcher programs, all platform-dependent binaries
|
||||
are under the lib/ directory. Ren'Py itself has now been placed in the
|
||||
renpy/ directory. The common/ directory has been moved to
|
||||
renpy/common/, as it's considered an integral part of Ren'Py.
|
||||
The file layout of Ren'Py games has been somewhat altered. With the exception
|
||||
of small launcher programs, all platform-dependent binaries are under the
|
||||
lib/ directory. Ren'Py itself has now been placed in the renpy/ directory.
|
||||
The common/ directory has been moved to renpy/common/, as it's considered an
|
||||
integral part of Ren'Py.
|
||||
|
||||
Ren'Py now uses renamed but otherwise unmodified python binaries on
|
||||
all desktop platforms. (Previously, it used platform-specific
|
||||
binaries.) Portions of the library are shared between the desktop
|
||||
builds.
|
||||
Ren'Py now uses renamed but otherwise unmodified python binaries on all
|
||||
desktop platforms. (Previously, it used platform-specific binaries.) Portions
|
||||
of the library are shared between the desktop builds.
|
||||
|
||||
A running Ren'Py process on Linux will now be named after the game, rather
|
||||
than having python as a name.
|
||||
|
||||
A running Ren'Py process on Linux will now be named after the game,
|
||||
rather than having python as a name.
|
||||
|
||||
|
||||
|
||||
|
||||
Other Changes
|
||||
-------------
|
||||
|
||||
* :ref:`Viewports <sl-viewport>` now support edge scrolling, which
|
||||
scrolls the viewport when the mouse is within a a configurable
|
||||
distance of the viewport edge.
|
||||
* :ref:`Viewports <sl-viewport>` now support edge scrolling, which scrolls
|
||||
the viewport when the mouse is within a a configurable distance of the
|
||||
viewport edge.
|
||||
|
||||
* Most keyboard keys now automatically repeat. The repeat rate is
|
||||
controlled by :var:`config.key_repeat`.
|
||||
* Most keyboard keys now automatically repeat. The repeat rate is controlled
|
||||
by :var:`config.key_repeat`.
|
||||
|
||||
* Side images can now be used with menus.
|
||||
|
||||
* The :ref:`config.enter_yesno_transition` and `config.exit_yesno_transition`
|
||||
variables make it possible to define a transition that is run when
|
||||
yes/no prompts appear and disappear, respectively.
|
||||
|
||||
* The :ref:`config.enter_yesno_transition` and
|
||||
`config.exit_yesno_transition` variables make it possible to define a
|
||||
transition that is run when yes/no prompts appear and disappear,
|
||||
respectively.
|
||||
|
||||
* The :ref:`viewport statement <sl-viewport>` now supports edge scrolling -
|
||||
automatic scrolling when the mouse approaches the sides of the viewport.
|
||||
@@ -231,20 +293,21 @@ Among others, the following bugs were fixed:
|
||||
|
||||
* :ghbug:`51`: The slow_done callback was not called after a rollback.
|
||||
|
||||
* :ghbug:`56`, :ghbug:`57`: :func:`renpy.loadable` now works with Android assets.
|
||||
* :ghbug:`56`, :ghbug:`57`: :func:`renpy.loadable` now works with Android
|
||||
assets.
|
||||
|
||||
* :ghbug:`60`: Fixed a bug that prevented {p} and {w} from working properly when followed
|
||||
immediately by a text tag.
|
||||
|
||||
* :ghbug:`61`: Ren'Py no longer crashes when an end_game_transition is
|
||||
set and a screen uses a variable that is no longer defined when the
|
||||
game restarts.
|
||||
* :ghbug:`60`: Fixed a bug that prevented {p} and {w} from working properly
|
||||
when followed immediately by a text tag.
|
||||
|
||||
* :ghbug:`65`: Multiplying a rollback list by a number now always produces
|
||||
a rollback list.
|
||||
* :ghbug:`61`: Ren'Py no longer crashes when an end_game_transition is set
|
||||
and a screen uses a variable that is no longer defined when the game
|
||||
restarts.
|
||||
|
||||
* :ghbug:`65`: Multiplying a rollback list by a number now always produces a
|
||||
rollback list.
|
||||
|
||||
* Editra should work better on Windows.
|
||||
|
||||
|
||||
* It's now possible to :func:`renpy.call` a label that doesn't take
|
||||
parameters.
|
||||
|
||||
@@ -254,7 +317,7 @@ Among others, the following bugs were fixed:
|
||||
* Fixed an error handling failure when a python early block contained a
|
||||
syntax error.
|
||||
|
||||
|
||||
|
||||
|
||||
Ren'Py 6.14
|
||||
===========
|
||||
@@ -478,7 +541,7 @@ Other Changes
|
||||
|
||||
* The :func:`renpy.call` function allows - with major and important caveats
|
||||
- a call to a Ren'Py label to begin from inside python code. Such a call
|
||||
immediately terminates the current statement.
|
||||
immediately terminates the current statement.
|
||||
|
||||
* When an action is expected, nested lists of actions can be given. The
|
||||
lists are flattened and the action executed.
|
||||
|
||||
@@ -934,6 +934,18 @@ Rarely or Internally Used
|
||||
wav files are of a lower rate, changing this to that rate may make
|
||||
things more efficent.
|
||||
|
||||
.. var:: config.start_callbacks = [ ... ]
|
||||
|
||||
A list of callbacks functions that are called with no arguments
|
||||
after the init phase, but before the game (including the
|
||||
splashscreen) starts. This is intended to be used by frameworks
|
||||
to initialize variables that will be saved.
|
||||
|
||||
The default value of this variable includes callbacks that Ren'Py
|
||||
uses internally to implement features such as nvl-mode. New
|
||||
callbacks can be appended to this list, but the existing callbacks
|
||||
should not be removed.
|
||||
|
||||
.. var:: config.start_interact_callbacks = ...
|
||||
|
||||
A list of functions that are called (without any arguments) when
|
||||
|
||||
@@ -1,5 +1,18 @@
|
||||
.. Automatically generated file - do not modify.
|
||||
|
||||
.. function:: Flatten(child, **properties)
|
||||
|
||||
This flattens `child`, which may be made up of multiple textures, into
|
||||
a single texture.
|
||||
|
||||
Certain operations, like the alpha transform property, apply to every
|
||||
texture making up a displayable, which can yield incorrect results
|
||||
when the textures overlap on screen. Flatten creates a single texture
|
||||
from multiple textures, which can prevent this problem.
|
||||
|
||||
Flatten is a relatively expensive operation, and so should only be used
|
||||
when absolutely required.
|
||||
|
||||
.. function:: Frame(image, xborder, yborder, tile=False, **properties)
|
||||
|
||||
A displayable that resizes an image to fill the available area,
|
||||
|
||||
@@ -63,9 +63,12 @@
|
||||
One of ``"gl"`` or ``"sw"``, corresponding to the OpenGL and
|
||||
software renderers, respectively.
|
||||
|
||||
``"resizable``
|
||||
``"resizable"``
|
||||
True if and only if the window is resizable.
|
||||
|
||||
``"additive"``
|
||||
True if and only if the renderer supports additive blending.
|
||||
|
||||
Other, renderer-specific, keys may also exist. The dictionary should
|
||||
be treated as immutable. This should only be called once the display
|
||||
has been started (that is, after the init code is finished).
|
||||
|
||||
@@ -55,11 +55,14 @@
|
||||
textbutton "Marsopolis":
|
||||
action [ Jump("mars"), SelectedIf(mars_flag) ]
|
||||
|
||||
.. function:: Skip()
|
||||
.. function:: Skip(fast=False)
|
||||
|
||||
Causes the game to begin skipping. If the game is in a menu
|
||||
context, then this returns to the game. Otherwise, it just
|
||||
enables skipping.
|
||||
|
||||
`fast`
|
||||
If True, skips directly to the next menu choice.
|
||||
|
||||
.. function:: With(transition)
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,18 @@
|
||||
Dealing with Problems
|
||||
=====================
|
||||
|
||||
.. include:: display_problems.rst
|
||||
|
||||
|
||||
64-Bit Linux Problems
|
||||
----------------------
|
||||
|
||||
Ren'Py 6.14.x and 6.15.0-3 were compiled incorrectly, and will often
|
||||
fail to operate on 64-bit Linux computers. The best way to work around
|
||||
this is to download Ren'Py 6.15.4 or later, and use it to run the game::
|
||||
|
||||
|
||||
/path/to/renpy-6.15.4/renpy.sh /path/to/game-with-problems
|
||||
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user