texture_2d *text_manager_get_text(const char *font_name, int size, const char *text, rgba *color, int max_width, int text_style, float stroke_width) { char buf[256] = {'\0'}; float scale = device_get_text_scale(); snprintf(buf, sizeof(buf), "@TEXT%s|%i|%i|%i|%i|%i|%i|%i|%f|%s", font_name,(int) (scale * size), (int) (255 * color->r), (int) (255 * color->g), (int) (255 * color->b), (int) (255 * color->a), (int)(scale * max_width), text_style, scale * stroke_width, text); // text has to go last! texture_2d *tex = texture_manager_get_texture(texture_manager_get(), buf); if (!tex) { tex = texture_manager_load_texture(texture_manager_get(), buf); tex->originalWidth /= scale; tex->originalHeight /= scale; tex->width /= scale; tex->height /= scale; } return tex; }
/** * @name context_2d_delete * @brief frees the given context * @param ctx - (context_2d *) context to delete * @retval NONE */ void context_2d_delete(context_2d *ctx) { texture_2d *tex = texture_manager_get_texture(texture_manager_get(), (char *)ctx->url); if (tex) { texture_manager_free_texture(texture_manager_get(), tex); } free(ctx->url); free(ctx); }
/** * @name tealeaf_canvas_bind_texture_buffer * @brief binds the given context's texture backing to gl to draw to * @param ctx - (context_2d *) pointer to the context to bind * @retval NONE */ void tealeaf_canvas_bind_texture_buffer(context_2d *ctx) { texture_2d *tex = texture_manager_get_texture(texture_manager_get(), ctx->url); if (!tex) { return; } GLTRACE(glBindTexture(GL_TEXTURE_2D, tex->name)); GLTRACE(glFinish()); GLTRACE(glBindFramebuffer(GL_FRAMEBUFFER, canvas.offscreen_framebuffer)); GLTRACE(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex->name, 0)); canvas.framebuffer_width = tex->originalWidth; canvas.framebuffer_height = tex->originalHeight; canvas.framebuffer_offset_bottom = tex->height - tex->originalHeight; }
/** * @name core_tick * @brief moves the game forward by a single tick, defined by a time delta of * last tick to this tick * @param dt - (int) elapsed time from last tick to this tick in milliseconds * @retval NONE */ void core_tick(int dt) { if (js_ready) { core_timer_tick(dt); js_tick(dt); } // Tick the texture manager (load pending textures) texture_manager_tick(texture_manager_get()); /* * we need to wait 2 frames before removing the preloader after we get the * core_hide_preloader call from JS. Only on the second frame after the * callback are the images that were preloaded actually drawn. */ if (show_preload || preload_hide_frame_count < 2) { //if we've gotten the core_hide_preloader cb, start counting frames if (!show_preload) { preload_hide_frame_count++; } texture_2d *tex = texture_manager_get_texture(texture_manager_get(), "loading.png"); if (tex && tex->loaded) { if (do_sizing) { calculate_size(tex); do_sizing = false; } context_2d *ctx = context_2d_get_onscreen(tealeaf_canvas_get()); context_2d_loadIdentity(ctx); context_2d_clear(ctx); context_2d_drawImage(ctx, 0, "loading.png", &tex_size, &size, 0); // we're the first, last, and only thing to draw, so flush the buffer context_2d_flush(ctx); } } // check the gl error and send it to java to be logged if (js_ready) { core_check_gl_error(); } }
/** * @name context_2d_init * @brief init's and returns a context_2d pointer with the given options * @param canvas - (tealeaf_canvas *) canvas to use as the context's canvas * @param url - (const char *) name of the canvas * @param dest_tex - (int) * @param on_screen - (bool) whether this should be an onscreen or offscreen context * @retval context_2d* - pointer to the created context */ context_2d *context_2d_init(tealeaf_canvas *canvas, const char *url, int dest_tex, bool on_screen) { context_2d *ctx = (context_2d *) malloc(sizeof(context_2d)); ctx->mvp = 0; ctx->globalAlpha[0] = 1; ctx->globalCompositeOperation[0] = 0; ctx->destTex = dest_tex; ctx->on_screen = on_screen; ctx->filter_color.r = 0.0; ctx->filter_color.g = 0.0; ctx->filter_color.b = 0.0; ctx->filter_color.a = 0.0; ctx->filter_type = FILTER_NONE; if (!on_screen) { texture_2d *tex = texture_manager_get_texture(texture_manager_get(), url); if (tex) { ctx->backing_width = tex->width; ctx->backing_height = tex->height; ctx->width = tex->originalWidth; ctx->height = tex->originalHeight; tealeaf_context_set_proj_matrix(ctx); tex->ctx = ctx; } } else { ctx->width = 0; ctx->height = 0; } ctx->canvas = canvas; int len = strlen(url); ctx->url = (char *)malloc(sizeof(char) * (len + 1)); strlcpy(ctx->url, url, len + 1); ctx->clipStack[0].x = 0; ctx->clipStack[0].y = 0; ctx->clipStack[0].width = -1; ctx->clipStack[0].height = -1; matrix_3x3_identity(&ctx->modelView[0]); context_2d_clear(ctx); return ctx; }
/** * @name core_tick * @brief moves the game forward by a single tick, defined by a time delta of * last tick to this tick * @param dt - (int) elapsed time from last tick to this tick in milliseconds * @retval NONE */ void core_tick(int dt) { if (js_ready) { core_timer_tick(dt); js_tick(dt); } // Tick the texture manager (load pending textures) texture_manager_tick(texture_manager_get()); /* * we need to wait 2 frames before removing the preloader after we get the * core_hide_preloader call from JS. Only on the second frame after the * callback are the images that were preloaded actually drawn. */ if (show_preload || preload_hide_frame_count < 2) { //if we've gotten the core_hide_preloader cb, start counting frames if (!show_preload) { preload_hide_frame_count++; // May have never loaded the splash image, so hide splash here too device_hide_splash(); } // If splash is defined, const char *splash = config_get_splash(); if (splash) { texture_2d *tex = texture_manager_get_texture(texture_manager_get(), splash); if (!tex) { tex = texture_manager_load_texture(texture_manager_get(), splash); } if (tex && tex->loaded) { if (do_sizing) { // Calculate rotation tealeaf_canvas *canvas = tealeaf_canvas_get(); int canvas_width = canvas->framebuffer_width; int canvas_height = canvas->framebuffer_height; rotate = canvas_width > canvas_height; rotate ^= tex->originalWidth > tex->originalHeight; calculate_size(tex, rotate); do_sizing = false; } context_2d *ctx = context_2d_get_onscreen(tealeaf_canvas_get()); context_2d_loadIdentity(ctx); context_2d_clear(ctx); if (rotate) { context_2d_save(ctx); context_2d_translate(ctx, size.y + (size.height)/2.f/tex->scale, size.x + (size.width)/2.f/tex->scale); context_2d_rotate(ctx, (tex->originalWidth > tex->originalHeight)? -3.14f/2.f : 3.14f/2.f); context_2d_translate(ctx, -size.x -(size.width)/2.f/tex->scale, -size.y - (size.height)/2.f/tex->scale); } context_2d_setGlobalCompositeOperation(ctx, source_over); context_2d_drawImage(ctx, 0, splash, &tex_size, &size); if (rotate) { context_2d_restore(ctx); } // we're the first, last, and only thing to draw, so flush the buffer context_2d_flush(ctx); device_hide_splash(); } } } // check the gl error and send it to java to be logged if (js_ready) { core_check_gl_error(); } }