d_define_method(drawable, normalize_scale)(struct s_object *self, double reference_w, double reference_h, double offset_x, double offset_y, double focus_x, double focus_y, double current_w, double current_h, double zoom) { d_using(drawable); double this_x, this_y, this_w, this_h, this_center_x, this_center_y, new_x, new_y, new_w, new_h, new_center_x, new_center_y, this_zoom; struct s_object *result = self; d_call(&(drawable_attributes->point_destination), m_point_get, &this_x, &this_y); d_call(&(drawable_attributes->point_dimension), m_point_get, &this_w, &this_h); d_call(&(drawable_attributes->point_center), m_point_get, &this_center_x, &this_center_y); new_x = (this_x + this_center_x) - (this_center_x * drawable_attributes->zoom); new_y = (this_y + this_center_y) - (this_center_y * drawable_attributes->zoom); new_x = (new_x + focus_x) - (focus_x * zoom); new_y = (new_y + focus_y) - (focus_y * zoom); new_x = ((new_x * current_w)/reference_w) - offset_x; new_y = ((new_y * current_h)/reference_h) - offset_y; this_zoom = drawable_attributes->zoom * zoom; new_w = ((this_w * current_w)/reference_w) * this_zoom; new_h = ((this_h * current_h)/reference_h) * this_zoom; new_center_x = ((this_center_x * new_w)/this_w) * zoom; new_center_y = ((this_center_y * new_h)/this_h) * zoom; d_call(&(drawable_attributes->point_normalized_destination), m_point_set_x, new_x); d_call(&(drawable_attributes->point_normalized_destination), m_point_set_y, new_y); d_call(&(drawable_attributes->point_normalized_dimension), m_point_set_x, new_w); d_call(&(drawable_attributes->point_normalized_dimension), m_point_set_y, new_h); d_call(&(drawable_attributes->point_normalized_center), m_point_set_x, new_center_x); d_call(&(drawable_attributes->point_normalized_center), m_point_set_y, new_center_y); /* is the object still visible ? */ if ((drawable_attributes->flags&e_drawable_kind_force_visibility) != e_drawable_kind_force_visibility) if ((new_x > current_w) || (new_y > current_h) || (new_x < -new_w) || (new_y < -new_h)) result = NULL; return result; }
d_define_method_override(container, draw)(struct s_object *self, struct s_object *environment) { d_using(container); struct s_drawable_attributes *drawable_attributes_self = d_cast(self, drawable), *drawable_attributes_entry; struct s_uiable_attributes *uiable_attributes_self = d_cast(self, uiable), *uiable_attributes_entry; struct s_square_attributes *square_attributes; struct s_environment_attributes *environment_attributes = d_cast(environment, environment); struct s_camera_attributes *camera_attributes = d_cast(environment_attributes->current_camera, camera); struct s_container_drawable *current_container; double position_x_self, position_y_self, normalized_position_x_self, normalized_position_y_self, position_x_entry, position_y_entry, center_x_self, center_y_self, center_x_entry, center_y_entry, max_w = container_attributes->border_left + container_attributes->border_right, max_h = container_attributes->border_top + container_attributes->border_bottom, current_w, current_h; int result = d_drawable_return_last; d_call(&(drawable_attributes_self->point_destination), m_point_get, &position_x_self, &position_y_self); d_call(&(drawable_attributes_self->point_normalized_destination), m_point_get, &normalized_position_x_self, &normalized_position_y_self); d_call(&(drawable_attributes_self->point_center), m_point_get, ¢er_x_self, ¢er_y_self); d_foreach(&(container_attributes->entries), current_container, struct s_container_drawable) { drawable_attributes_entry = d_cast(current_container->drawable, drawable); position_x_entry = position_x_self + current_container->position_x + container_attributes->border_left; position_y_entry = position_y_self + current_container->position_y + container_attributes->border_top; center_x_entry = (position_x_self + center_x_self) - position_x_entry; center_y_entry = (position_y_self + center_y_self) - position_y_entry; d_call(current_container->drawable, m_drawable_set_position, position_x_entry, position_y_entry); if (((drawable_attributes_entry->flags & e_drawable_kind_ui_no_attribute_angle) != e_drawable_kind_ui_no_attribute_angle) && ((drawable_attributes_entry->flags & e_drawable_kind_ui_no_attribute_zoom) != e_drawable_kind_ui_no_attribute_zoom)) d_call(current_container->drawable, m_drawable_set_center, center_x_entry, center_y_entry); if ((drawable_attributes_entry->flags & e_drawable_kind_ui_no_attribute_angle) != e_drawable_kind_ui_no_attribute_angle) drawable_attributes_entry->angle = drawable_attributes_self->angle; if ((drawable_attributes_entry->flags & e_drawable_kind_ui_no_attribute_zoom) != e_drawable_kind_ui_no_attribute_zoom) drawable_attributes_entry->zoom = container_attributes->distributed_zoom; if ((drawable_attributes_entry->flags & e_drawable_kind_ui_no_attribute_flip) != e_drawable_kind_ui_no_attribute_flip) drawable_attributes_entry->flip = drawable_attributes_self->flip; if ((d_call(current_container->drawable, m_drawable_normalize_scale, camera_attributes->scene_reference_w, camera_attributes->scene_reference_h, camera_attributes->scene_offset_x, camera_attributes->scene_offset_y, camera_attributes->scene_center_x, camera_attributes->scene_center_y, camera_attributes->screen_w, camera_attributes->screen_h, camera_attributes->scene_zoom))) { square_attributes = d_cast(&(drawable_attributes_entry->square_collision_box), square); current_w = d_math_max(d_math_max(square_attributes->normalized_top_left_x, square_attributes->normalized_top_right_x), d_math_max(square_attributes->normalized_bottom_left_x, square_attributes->normalized_bottom_right_x)) - normalized_position_x_self; current_h = d_math_max(d_math_max(square_attributes->normalized_top_left_y, square_attributes->normalized_top_right_y), d_math_max(square_attributes->normalized_bottom_left_y, square_attributes->normalized_bottom_right_y)) - normalized_position_y_self; if ((uiable_attributes_entry = d_cast(current_container->drawable, uiable))) { /* we need to take in consideration the border of the object that is not considered in the collision square */ current_w += uiable_attributes_entry->border_w; current_h += uiable_attributes_entry->border_h; } /* normalization for ratio and environmental zoom */ current_w = ((current_w * camera_attributes->scene_reference_w) / camera_attributes->screen_w) / camera_attributes->scene_zoom; current_h = ((current_h * camera_attributes->scene_reference_h) / camera_attributes->screen_h) / camera_attributes->scene_zoom; max_w = d_math_max(max_w, current_w); max_h = d_math_max(max_h, current_h); } } d_call(self, m_drawable_set_dimension, (max_w + uiable_attributes_self->border_w), (max_h + uiable_attributes_self->border_h)); if ((d_call(self, m_drawable_normalize_scale, camera_attributes->scene_reference_w, camera_attributes->scene_reference_h, camera_attributes->scene_offset_x, camera_attributes->scene_offset_y, camera_attributes->scene_center_x, camera_attributes->scene_center_y, camera_attributes->screen_w, camera_attributes->screen_h, camera_attributes->scene_zoom))) { result = (intptr_t)d_call_owner(self, uiable, m_drawable_draw, environment); /* recall the father's draw method */ d_foreach(&(container_attributes->entries), current_container, struct s_container_drawable) while (((intptr_t)d_call(current_container->drawable, m_drawable_draw, environment)) == d_drawable_return_continue); }
d_define_method_override(label, set_dimension)(struct s_object *self, double w, double h) { d_using(label); struct s_drawable_attributes *drawable_attributes = d_cast(self, drawable); struct s_object *result = d_call_owner(self, drawable, m_drawable_set_dimension, w, h); label_attributes->last_width = w; label_attributes->last_height = h; label_attributes->format = e_label_background_format_fixed; d_call(&(drawable_attributes->point_center), m_point_set_x, (double)(label_attributes->last_width/2.0)); d_call(&(drawable_attributes->point_center), m_point_set_y, (double)(label_attributes->last_height/2.0)); return result; }
d_define_method(stream, write_stream)(struct s_object *self, struct s_object *stream, size_t *written) { unsigned char block[d_stream_block_size]; size_t readed, written_local = 0; d_call(stream, m_stream_seek, 0, e_stream_seek_begin, NULL); while ((d_call(stream, m_stream_read, block, d_stream_block_size, &readed)) && (readed > 0)) { d_call(self, m_stream_write, block, readed, &written_local); if (*written) *written += written_local; } return self; }
d_define_method(uiable, set)(struct s_object *self, struct s_object *drawable, enum e_uiable_components component) { d_using(uiable); if (uiable_attributes->background[component]) d_delete(uiable_attributes->background[component]); uiable_attributes->background[component] = d_retain(drawable); if (uiable_attributes->last_blend != e_drawable_blend_undefined) d_call(uiable_attributes->background[component], m_drawable_set_blend, uiable_attributes->last_blend); d_call(uiable_attributes->background[component], m_drawable_set_maskRGB, (unsigned int)uiable_attributes->last_mask_R, (unsigned int)uiable_attributes->last_mask_G, (unsigned int)uiable_attributes->last_mask_B); d_call(uiable_attributes->background[component], m_drawable_set_maskA, (unsigned int)uiable_attributes->last_mask_A); return self; }
d_define_method(illuminable_bitmap, set_light_mask)(struct s_object *self, struct s_object *drawable_mask, enum e_illuminable_bitmap_sides side) { d_using(illuminable_bitmap); double mask_width, mask_height, image_width, image_height; if (illuminable_bitmap_attributes->drawable_mask[side]) d_delete(illuminable_bitmap_attributes->drawable_mask[side]); illuminable_bitmap_attributes->drawable_mask[side] = d_retain(drawable_mask); d_call(illuminable_bitmap_attributes->drawable_mask[side], m_drawable_set_blend, e_drawable_blend_add); d_call(illuminable_bitmap_attributes->drawable_mask[side], m_drawable_get_dimension, &mask_width, &mask_height); d_call(self, m_drawable_get_dimension, &image_width, &image_height); d_assert((image_width == mask_width)); d_assert((image_height == mask_height)); return self; }
struct s_object *f_container_new(struct s_object *self, double border_top, double border_bottom, double border_left, double border_right, t_boolean floatable) { struct s_container_attributes *attributes = p_container_alloc(self); attributes->border_top = border_top; attributes->border_bottom = border_bottom; attributes->border_left = border_left; attributes->border_right = border_right; attributes->distributed_zoom = 1; if ((attributes->floatable = floatable)) { d_call(self, m_morphable_set_freedom_x, d_true); d_call(self, m_morphable_set_freedom_y, d_true); } return self; }
d_define_method_override(container, event)(struct s_object *self, struct s_object *environment, SDL_Event *current_event) { d_using(container); struct s_eventable_attributes *eventable_attributes; struct s_uiable_attributes *uiable_attributes; struct s_container_drawable *current_container; struct s_object *result = d_call_owner(self, uiable, m_eventable_event, environment, current_event); struct s_exception *exception; d_try { d_foreach(&(container_attributes->entries), current_container, struct s_container_drawable) { if (((uiable_attributes = d_cast(current_container->drawable, uiable))) && ((eventable_attributes = d_cast(current_container->drawable, eventable)))) { d_call_owner(current_container->drawable, uiable, m_eventable_event, environment, current_event); if ((uiable_attributes->is_selected) && (eventable_attributes->enable)) d_call(current_container->drawable, m_eventable_event, environment, current_event); } } } d_catch(exception) { d_exception_dump(stderr, exception); d_raise; } d_endtry; return result; }
d_define_method(environment, run_loop)(struct s_object *self) { d_using(environment); int starting_time = SDL_GetTicks(), current_time, waiting_time, required_time = (int)(1000.0f/environment_attributes->fps), surface, index, flags; struct s_object *drawable_object; struct s_object *eventable_object; struct s_exception *exception; SDL_Event local_event; environment_attributes->init_call(self); while (environment_attributes->continue_loop) { d_try { if (SDL_PollEvent(&local_event)) { d_foreach(&(environment_attributes->eventable), eventable_object, struct s_object) d_call(eventable_object, m_eventable_event, self, &local_event); if (local_event.type == SDL_QUIT) environment_attributes->continue_loop = d_false; } SDL_RenderClear(environment_attributes->renderer); if (environment_attributes->main_call(self)) { for (surface = 0; surface < e_environment_surface_NULL; ++surface) for (index = 0; index < d_environment_layers; ++index) d_foreach(&(environment_attributes->drawable[surface][index]), drawable_object, struct s_object) { flags = (int)d_call(drawable_object, m_drawable_get_flags, NULL); if ((flags&e_drawable_kind_hidden) != e_drawable_kind_hidden) if ((d_call(drawable_object, m_drawable_normalize_scale, environment_attributes->reference_w, environment_attributes->reference_h, environment_attributes->camera_origin_x, environment_attributes->camera_origin_y, environment_attributes->camera_focus_x, environment_attributes->camera_focus_y, environment_attributes->current_w, environment_attributes->current_h, environment_attributes->zoom))) while (((int)d_call(drawable_object, m_drawable_draw, self)) == d_drawable_return_continue); } current_time = SDL_GetTicks(); if ((waiting_time = required_time - (current_time - starting_time)) > 0) SDL_Delay(waiting_time); else if (waiting_time < (d_environment_tolerance * -1)) d_war(e_log_level_medium, "loop time has a delay of %d mS", (waiting_time * -1)); starting_time = current_time; /* align the FPS time delay and then refresh the image */ SDL_RenderPresent(environment_attributes->renderer); } else environment_attributes->continue_loop = d_false; } d_catch(exception) {
d_define_method(stream, size)(struct s_object *self, size_t *size) { d_using(stream); off_t offset, current_offset; if ((stream_attributes->flags&e_stream_flag_opened) == e_stream_flag_opened) { if (((stream_attributes->parameters&O_RDWR) == O_RDWR) || ((stream_attributes->parameters&O_RDONLY) == O_RDONLY)) { d_call(self, m_stream_seek, 0, e_stream_seek_current, ¤t_offset); d_call(self, m_stream_seek, 0, e_stream_seek_begin, NULL); d_call(self, m_stream_seek, 0, e_stream_seek_end, &offset); if (size) *size = (size_t)offset; d_call(self, m_stream_seek, current_offset, e_stream_seek_begin); } else d_throw(v_exception_unsupported, "read in a write-only stream exception"); } else d_throw(v_exception_closed, "read in a closed stream exception"); return self; }
d_define_method_override(uiable, set_blend)(struct s_object *self, enum e_drawable_blends blend) { d_using(uiable); int index; uiable_attributes->last_blend = blend; for (index = 0; index < e_uiable_component_NULL; ++index) if (uiable_attributes->background[index]) d_call(uiable_attributes->background[index], m_drawable_set_blend, blend); return self; }
d_define_method_override(uiable, set_maskA)(struct s_object *self, unsigned int alpha) { d_using(uiable); int index; uiable_attributes->last_mask_A = alpha; for (index = 0; index < e_uiable_component_NULL; ++index) if (uiable_attributes->background[index]) d_call(uiable_attributes->background[index], m_drawable_set_maskA, (unsigned int)alpha); return self; }
d_define_method(emitter, raise)(struct s_object *self, const char *id) { struct s_signal *signal; void *result = NULL; if ((signal = d_call(self, m_emitter_get, id))) { d_log(e_log_level_high, "signal '%s' has been raised from %s (%s::%d)", id, self->type, self->file, self->line); if (signal->action) result = signal->action(self, signal->parameters, signal->parameters_size); } return result; }
d_define_method_override(checkbox, event)(struct s_object *self, struct s_object *environment, SDL_Event *current_event) { d_using(checkbox); struct s_uiable_attributes *uiable_attributes = d_cast(self, uiable); if ((current_event->type == SDL_MOUSEBUTTONUP) && (current_event->button.button == SDL_BUTTON_LEFT)) { if (uiable_attributes->selected_mode == e_uiable_mode_selected) checkbox_attributes->is_checked = !checkbox_attributes->is_checked; d_call(self, m_uiable_mode, e_uiable_mode_active); } return self; }
struct s_object * f_particle_new(struct s_object *self, struct s_object *drawable_particle, struct s_object *environment, struct s_particle_configuration *configuration) { struct s_particle_attributes *attributes = p_particle_alloc(self); attributes->drawable_core = d_retain(drawable_particle); memcpy(&(attributes->configuration), configuration, sizeof(struct s_particle_configuration)); memset(&(attributes->particles), 0, (sizeof(struct s_particle_information) * d_particle_cores)); d_call(attributes->drawable_core, m_drawable_set_blend, attributes->configuration.blend); attributes->single_shoot = attributes->configuration.single_shoot; attributes->initialized = d_false; return self; }
d_define_method_override(bitmap, draw)(struct s_object *self, struct s_object *environment) { d_using(bitmap); double position_x, position_y, dimension_w, dimension_h, center_x, center_y; struct s_drawable_attributes *drawable_attributes = d_cast(self, drawable); struct s_environment_attributes *environment_attributes = d_cast(environment, environment); SDL_Rect destination; SDL_Point center; d_call(&(drawable_attributes->point_normalized_destination), m_point_get, &position_x, &position_y); d_call(&(drawable_attributes->point_normalized_dimension), m_point_get, &dimension_w, &dimension_h); d_call(&(drawable_attributes->point_normalized_center), m_point_get, ¢er_x, ¢er_y); destination.x = position_x; destination.y = position_y; destination.w = dimension_w; destination.h = dimension_h; center.x = center_x; center.y = center_y; SDL_RenderCopyEx(environment_attributes->renderer, bitmap_attributes->image, NULL, &destination, drawable_attributes->angle, ¢er, drawable_attributes->flip); d_cast_return(d_drawable_return_last); }
d_define_method_override(uiable, set_maskRGB)(struct s_object *self, unsigned int red, unsigned int green, unsigned int blue) { d_using(uiable); int index; uiable_attributes->last_mask_R = red; uiable_attributes->last_mask_G = green; uiable_attributes->last_mask_B = blue; for (index = 0; index < e_uiable_component_NULL; ++index) if (uiable_attributes->background[index]) d_call(uiable_attributes->background[index], m_drawable_set_maskRGB, (unsigned int)red, (unsigned int)green, (unsigned int)blue); return self; }
d_define_method_override(particle, draw)(struct s_object *self, struct s_object *environment) { d_using(particle); unsigned int index, new_particles; struct timeval current, elapsed_update; double real_elapsed_update, local_position_x, local_position_y, position_x, position_y, normalized_R, normalized_G, normalized_B, normalized_A; struct s_drawable_attributes *drawable_attributes_core = d_cast(particle_attributes->drawable_core, drawable), *drawable_attributes_self = d_cast(self, drawable); struct s_environment_attributes *environment_attributes = d_cast(environment, environment); struct s_camera_attributes *camera_attributes = d_cast(environment_attributes->current_camera, camera); gettimeofday(¤t, NULL); if (!particle_attributes->initialized) { memcpy(&(particle_attributes->last_generation), ¤t, sizeof(struct timeval)); particle_attributes->initialized = d_true; } timersub(¤t, &(particle_attributes->last_generation), &elapsed_update); real_elapsed_update = elapsed_update.tv_sec + ((double)(elapsed_update.tv_usec) / 1000000.0); if ((new_particles = (unsigned int)(particle_attributes->configuration.emission_rate * real_elapsed_update)) > 0) memcpy(&(particle_attributes->last_generation), ¤t, sizeof(struct timeval)); d_call(self, m_particle_update, new_particles); d_call(&(drawable_attributes_self->point_destination), m_point_get, (double *)&local_position_x, (double *)&local_position_y); for (index = 0; index < particle_attributes->configuration.particles; ++index) if (particle_attributes->particles[index].alive) { /* since the particle is a single object shared between all the emitters stored into the list, we should perform the normalization here, in the draw * method */ normalized_R = ((particle_attributes->particles[index].core.mask_R / 255.0) * (drawable_attributes_self->last_mask_R / 255.0)) * 255.0; normalized_G = ((particle_attributes->particles[index].core.mask_G / 255.0) * (drawable_attributes_self->last_mask_G / 255.0)) * 255.0; normalized_B = ((particle_attributes->particles[index].core.mask_B / 255.0) * (drawable_attributes_self->last_mask_B / 255.0)) * 255.0; normalized_A = ((particle_attributes->particles[index].core.mask_A / 255.0) * (drawable_attributes_self->last_mask_A / 255.0)) * 255.0; d_call(particle_attributes->drawable_core, m_drawable_set_maskRGB, (unsigned int)normalized_R, (unsigned int)normalized_G, (unsigned int)normalized_B); d_call(particle_attributes->drawable_core, m_drawable_set_maskA, (unsigned int)normalized_A); position_x = particle_attributes->particles[index].core.position_x; position_y = particle_attributes->particles[index].core.position_y; d_call(&(drawable_attributes_core->point_destination), m_point_set_x, (double)position_x); d_call(&(drawable_attributes_core->point_destination), m_point_set_y, (double)position_y); drawable_attributes_core->zoom = (particle_attributes->particles[index].core.zoom * drawable_attributes_self->zoom); drawable_attributes_core->angle = (particle_attributes->particles[index].core.angle + drawable_attributes_self->angle); drawable_attributes_core->flip = drawable_attributes_self->flip; if ((d_call(particle_attributes->drawable_core, m_drawable_normalize_scale, camera_attributes->scene_reference_w, camera_attributes->scene_reference_h, camera_attributes->scene_offset_x, camera_attributes->scene_offset_y, camera_attributes->scene_center_x, camera_attributes->scene_center_y, camera_attributes->screen_w, camera_attributes->screen_h, camera_attributes->scene_zoom))) while (((intptr_t)d_call(particle_attributes->drawable_core, m_drawable_draw, environment)) == d_drawable_return_continue); if ((drawable_attributes_self->flags & e_drawable_kind_contour) == e_drawable_kind_contour) d_call(particle_attributes->drawable_core, m_drawable_draw_contour, environment); } d_cast_return(d_drawable_return_last); }
d_define_method(emitter, embed_parameter)(struct s_object *self, const char *id, void *parameter) { struct s_signal *signal; void **new_parameters; if ((signal = d_call(self, m_emitter_get, id))) { signal->parameters_size++; if ((new_parameters = (void **) d_realloc(signal->parameters, (signal->parameters_size*sizeof(void *))))) { signal->parameters = new_parameters; signal->parameters[signal->parameters_size-1] = parameter; } } return (void *)signal; }
d_define_method_override(checkbox, draw)(struct s_object *self, struct s_object *environment) { d_using(checkbox); struct s_uiable_attributes *uiable_attributes = d_cast(self, uiable); struct s_environment_attributes *environment_attributes = d_cast(environment, environment); struct s_drawable_attributes *drawable_attributes_self = d_cast(self, drawable), *drawable_attributes_selected; struct s_object *selected_component = NULL; double position_x, position_y, new_position_x, new_position_y, center_x, center_y, new_center_x, new_center_y, dimension_w_self, dimension_h_self, dimension_w_selected, dimension_h_selected, new_dimension_w, new_dimension_h; int result = (intptr_t)d_call_owner(self, label, m_drawable_draw, environment); /* recall the father's draw method */ d_call(&(drawable_attributes_self->point_destination), m_point_get, &position_x, &position_y); d_call(&(drawable_attributes_self->point_dimension), m_point_get, &dimension_w_self, &dimension_h_self); d_call(&(drawable_attributes_self->point_center), m_point_get, ¢er_x, ¢er_y); if ((checkbox_attributes->is_checked) && (checkbox_attributes->checked)) selected_component = checkbox_attributes->checked; else if ((!checkbox_attributes->is_checked) && (checkbox_attributes->unchecked)) selected_component = checkbox_attributes->unchecked; if (selected_component) { drawable_attributes_selected = d_cast(selected_component, drawable); d_call(&(drawable_attributes_selected->point_dimension), m_point_get, &dimension_w_selected, &dimension_h_selected); new_dimension_h = dimension_h_self - (uiable_attributes->border_h * 2.0); new_dimension_w = (dimension_w_selected * new_dimension_h)/dimension_h_selected; new_position_x = position_x + dimension_w_self - new_dimension_w - uiable_attributes->border_w; new_position_y = position_y + ((dimension_h_self - new_dimension_h) / 2.0); new_center_x = (position_x + center_x) - new_position_x; new_center_y = (position_y + center_y) - new_position_y; d_call(selected_component, m_drawable_set_position, new_position_x, new_position_y); d_call(selected_component, m_drawable_set_center, new_center_x, new_center_y); d_call(selected_component, m_drawable_set_dimension, new_dimension_w, new_dimension_h); drawable_attributes_selected->angle = drawable_attributes_self->angle; drawable_attributes_selected->zoom = drawable_attributes_self->zoom; drawable_attributes_selected->flip = drawable_attributes_self->flip; if ((d_call(selected_component, m_drawable_normalize_scale, environment_attributes->reference_w[environment_attributes->current_surface], environment_attributes->reference_h[environment_attributes->current_surface], environment_attributes->camera_origin_x[environment_attributes->current_surface], environment_attributes->camera_origin_y[environment_attributes->current_surface], environment_attributes->camera_focus_x[environment_attributes->current_surface], environment_attributes->camera_focus_y[environment_attributes->current_surface], environment_attributes->current_w, environment_attributes->current_h, environment_attributes->zoom[environment_attributes->current_surface]))) while(((int)d_call(selected_component, m_drawable_draw, environment)) == d_drawable_return_continue); } d_cast_return(result); }
struct s_object *f_bitmap_new(struct s_object *self, struct s_object *stream, struct s_object *environment) { struct s_bitmap_attributes *attributes = p_bitmap_alloc(self); struct s_drawable_attributes *drawable_attributes = d_cast(self, drawable); struct s_stream_attributes *stream_attributes = d_cast(stream, stream); struct s_environment_attributes *environment_attributes = d_cast(environment, environment); char *memblock, buffer[d_string_buffer_size]; struct stat file_stats; int width, height; SDL_RWops *surfaced_block; SDL_Surface *unoptimized_surface; fstat(stream_attributes->descriptor, &file_stats); if ((memblock = mmap(NULL, file_stats.st_size, PROT_READ, MAP_SHARED, stream_attributes->descriptor, 0)) != MAP_FAILED) { surfaced_block = SDL_RWFromMem(memblock, file_stats.st_size); if ((unoptimized_surface = IMG_Load_RW(surfaced_block, d_true))) { attributes->image = SDL_CreateTextureFromSurface(environment_attributes->renderer, unoptimized_surface); if (SDL_QueryTexture(attributes->image, NULL, NULL, &width, &height) == 0) { d_call(&(drawable_attributes->point_dimension), m_point_set_x, (double)width); d_call(&(drawable_attributes->point_dimension), m_point_set_y, (double)height); d_call(&(drawable_attributes->point_center), m_point_set_x, (double)(width/2.0)); d_call(&(drawable_attributes->point_center), m_point_set_y, (double)(height/2.0)); } else { snprintf(buffer, d_string_buffer_size, "unable to retrieve informations for bitmap %s exception", d_string_cstring(stream_attributes->string_name)); d_throw(v_exception_texture, buffer); } } else { snprintf(buffer, d_string_buffer_size, "ungenerable texture for bitmap %s exception", d_string_cstring(stream_attributes->string_name)); d_throw(v_exception_texture, buffer); } SDL_FreeSurface(unoptimized_surface); munmap(memblock, file_stats.st_size); } else { snprintf(buffer, d_string_buffer_size, "wrong type for file %s exception", d_string_cstring(stream_attributes->string_name)); d_throw(v_exception_wrong_type, buffer); } return self; }
d_define_method(label, update_texture)(struct s_object *self, TTF_Font *font, struct s_object *environment) { d_using(label); char buffer[d_string_buffer_size]; int width, height; struct s_drawable_attributes *drawable_attributes = d_cast(self, drawable); struct s_uiable_attributes *uiable_attributes = d_cast(self, uiable); struct s_environment_attributes *environment_attributes = d_cast(environment, environment); TTF_Font *current_font; SDL_Surface *unoptimized_surface; SDL_Color white = { 255, 255, 255, 255 }; if (label_attributes->image) { SDL_DestroyTexture(label_attributes->image); label_attributes->image = NULL; } if ((current_font = font) || (current_font = label_attributes->last_font)) { label_attributes->last_font = current_font; if (f_string_strlen(label_attributes->string_content) > 0) { if ((unoptimized_surface = TTF_RenderText_Blended(current_font, label_attributes->string_content, white))) { label_attributes->image = SDL_CreateTextureFromSurface(environment_attributes->renderer, unoptimized_surface); if (SDL_QueryTexture(label_attributes->image, NULL, NULL, &width, &height) == 0) { label_attributes->string_width = width; label_attributes->string_height = height; if (label_attributes->format == e_label_background_format_adaptable) { label_attributes->last_width = width + (uiable_attributes->border_w * 2.0); label_attributes->last_height = height + (uiable_attributes->border_h * 2.0); } d_call(&(drawable_attributes->point_dimension), m_point_set_x, (double)label_attributes->last_width); d_call(&(drawable_attributes->point_dimension), m_point_set_y, (double)label_attributes->last_height); if (label_attributes->last_blend != e_drawable_blend_undefined) d_call(self, m_drawable_set_blend, label_attributes->last_blend); d_call(self, m_drawable_set_maskRGB, (unsigned int)label_attributes->last_mask_R, (unsigned int)label_attributes->last_mask_G, (unsigned int)label_attributes->last_mask_B); d_call(self, m_drawable_set_maskA, (unsigned int)label_attributes->last_mask_A); } else { snprintf(buffer, d_string_buffer_size, "unable to retrieve informations for label \"%s\" exception", label_attributes->string_content); d_throw(v_exception_texture, buffer); } SDL_FreeSurface(unoptimized_surface); } else { snprintf(buffer, d_string_buffer_size, "ungenerable texture for label \"%s\" exception", label_attributes->string_content); d_throw(v_exception_texture, buffer); } } } else { snprintf(buffer, d_string_buffer_size, "ungenerable texture for label \"%s\" with missing font exception", label_attributes->string_content); d_throw(v_exception_texture, buffer); } d_call(self, m_emitter_raise, v_uiable_signals[e_uiable_signal_content_changed]); return self; }
d_define_method(track, play_fade_in)(struct s_object *self, t_boolean restart, int delay) { d_using(track); t_boolean start_required = d_true; int channel; if ((track_attributes->channel != d_track_auto_channel) && ((Mix_Playing(track_attributes->channel)) || (Mix_Paused(track_attributes->channel)))) { if (restart) Mix_HaltChannel(track_attributes->channel); else { if (Mix_Paused(track_attributes->channel)) Mix_Resume(track_attributes->channel); start_required = d_false; } } if (start_required) { if (track_attributes->auto_channel) channel = d_track_auto_channel; else channel = track_attributes->next_channel; d_call(self, m_track_set_volume, track_attributes->volume); if ((track_attributes->channel = Mix_FadeInChannel(channel, track_attributes->chunk, track_attributes->loops, delay)) != -1) d_call(self, m_track_set_position, track_attributes->angle, track_attributes->distance); } return self; }
d_define_method(label, set_content)(struct s_object *self, struct s_object *string_content, TTF_Font *font, struct s_object *environment) { d_using(label); struct s_drawable_attributes *drawable_attributes = d_cast(self, drawable); struct s_environment_attributes *environment_attributes = d_cast(environment, environment); char buffer[d_string_buffer_size]; int width, height; SDL_Surface *unoptimized_surface; SDL_Color white = { 255, 255, 255, 255 }; if (label_attributes->string_content) d_delete(label_attributes->string_content); label_attributes->string_content = d_retain(string_content); if (label_attributes->image) SDL_DestroyTexture(label_attributes->image); if ((unoptimized_surface = TTF_RenderText_Blended(font, d_string_cstring(string_content), white))) { label_attributes->image = SDL_CreateTextureFromSurface(environment_attributes->renderer, unoptimized_surface); if (SDL_QueryTexture(label_attributes->image, NULL, NULL, &width, &height) == 0) { d_call(&(drawable_attributes->point_dimension), m_point_set_x, (double)width); d_call(&(drawable_attributes->point_dimension), m_point_set_y, (double)height); d_call(&(drawable_attributes->point_center), m_point_set_x, (double)(width/2.0)); d_call(&(drawable_attributes->point_center), m_point_set_y, (double)(height/2.0)); if (label_attributes->last_blend != e_drawable_blend_undefined) d_call(self, m_drawable_set_blend, label_attributes->last_blend); d_call(self, m_drawable_set_maskRGB, (unsigned int)label_attributes->last_mask_R, (unsigned int)label_attributes->last_mask_G, (unsigned int)label_attributes->last_mask_B); d_call(self, m_drawable_set_maskA, (unsigned int)label_attributes->last_mask_A); } else { snprintf(buffer, d_string_buffer_size, "unable to retrieve informations for label \"%s\" exception", d_string_cstring(string_content)); d_throw(v_exception_texture, buffer); } SDL_FreeSurface(unoptimized_surface); } else { snprintf(buffer, d_string_buffer_size, "ungenerable texture for label \"%s\" exception", d_string_cstring(string_content)); d_throw(v_exception_texture, buffer); } return self; }
d_define_method(uiable, draw)(struct s_object *self, struct s_object *environment) { d_using(uiable); struct s_environment_attributes *environment_attributes = d_cast(environment, environment); struct s_drawable_attributes *drawable_attributes_self = d_cast(self, drawable), *drawable_attributes_core; double local_x, local_y, local_w, local_h, center_x, center_y, component_w[e_uiable_component_NULL], component_h[e_uiable_component_NULL]; int index; d_call(&(drawable_attributes_self->point_destination), m_point_get, &local_x, &local_y); d_call(&(drawable_attributes_self->point_dimension), m_point_get, &local_w, &local_h); d_call(&(drawable_attributes_self->point_center), m_point_get, ¢er_x, ¢er_y); for (index = 0; index < e_uiable_component_NULL; ++index) if (uiable_attributes->background[index]) { drawable_attributes_core = d_cast(uiable_attributes->background[index], drawable); d_call(&(drawable_attributes_core->point_dimension), m_point_get, &(component_w[index]), &(component_h[index])); } if (uiable_attributes->background[e_uiable_component_center]) { d_call(uiable_attributes->background[e_uiable_component_center], m_drawable_set_position, (local_x-1), (local_y-1)); d_call(uiable_attributes->background[e_uiable_component_center], m_drawable_set_dimension, (local_w+2), (local_h+2)); d_call(uiable_attributes->background[e_uiable_component_center], m_drawable_set_center, (center_x+1), (center_y+1)); } if (uiable_attributes->background[e_uiable_component_corner_top_left]) { d_call(uiable_attributes->background[e_uiable_component_corner_top_left], m_drawable_set_position, (local_x-component_w[e_uiable_component_corner_top_left]), (local_y-component_h[e_uiable_component_corner_top_left])); d_call(uiable_attributes->background[e_uiable_component_corner_top_left], m_drawable_set_center, (center_x+component_w[e_uiable_component_corner_top_left]), (center_y+component_h[e_uiable_component_corner_top_left])); } if (uiable_attributes->background[e_uiable_component_corner_top_right]) { d_call(uiable_attributes->background[e_uiable_component_corner_top_right], m_drawable_set_position, (local_x+local_w), (local_y-component_h[e_uiable_component_corner_top_right])); d_call(uiable_attributes->background[e_uiable_component_corner_top_right], m_drawable_set_center, (center_x-local_w)-1, (center_y+component_h[e_uiable_component_corner_top_right])); } if (uiable_attributes->background[e_uiable_component_corner_bottom_left]) { d_call(uiable_attributes->background[e_uiable_component_corner_bottom_left], m_drawable_set_position, (local_x-component_w[e_uiable_component_corner_bottom_left]), (local_y+local_h)); d_call(uiable_attributes->background[e_uiable_component_corner_bottom_left], m_drawable_set_center, (center_x+component_w[e_uiable_component_corner_bottom_left]), (center_y-local_h)); } if (uiable_attributes->background[e_uiable_component_corner_bottom_right]) { d_call(uiable_attributes->background[e_uiable_component_corner_bottom_right], m_drawable_set_position, (local_x+local_w), (local_y+local_h)); d_call(uiable_attributes->background[e_uiable_component_corner_bottom_right], m_drawable_set_center, (center_x-local_w)-1, (center_y-local_h)-1); } if (uiable_attributes->background[e_uiable_component_top]) { d_call(uiable_attributes->background[e_uiable_component_top], m_drawable_set_position, (local_x-1), (local_y-component_h[e_uiable_component_top])); d_call(uiable_attributes->background[e_uiable_component_top], m_drawable_set_dimension_w, (local_w+2)); d_call(uiable_attributes->background[e_uiable_component_top], m_drawable_set_center, (center_x+1), (center_y+component_h[e_uiable_component_top])); } if (uiable_attributes->background[e_uiable_component_bottom]) { d_call(uiable_attributes->background[e_uiable_component_bottom], m_drawable_set_position, (local_x-1), (local_y+local_h)); d_call(uiable_attributes->background[e_uiable_component_bottom], m_drawable_set_dimension_w, (local_w+2)); d_call(uiable_attributes->background[e_uiable_component_bottom], m_drawable_set_center, (center_x+1), (center_y-local_h)); } if (uiable_attributes->background[e_uiable_component_left]) { d_call(uiable_attributes->background[e_uiable_component_left], m_drawable_set_position, (local_x-component_w[e_uiable_component_left]), (local_y-1)); d_call(uiable_attributes->background[e_uiable_component_left], m_drawable_set_dimension_h, (local_h+2)); d_call(uiable_attributes->background[e_uiable_component_left], m_drawable_set_center, (center_x+component_w[e_uiable_component_left]), (center_y+1)); } if (uiable_attributes->background[e_uiable_component_right]) { d_call(uiable_attributes->background[e_uiable_component_right], m_drawable_set_position, (local_x+local_w), (local_y-1)); d_call(uiable_attributes->background[e_uiable_component_right], m_drawable_set_dimension_h, (local_h+2)); d_call(uiable_attributes->background[e_uiable_component_right], m_drawable_set_center, (center_x-local_w)-1, (center_y+1)); } for (index = 0; index < e_uiable_component_NULL; ++index) if (uiable_attributes->background[index]) { drawable_attributes_core = d_cast(uiable_attributes->background[index], drawable); drawable_attributes_core->angle = drawable_attributes_self->angle; drawable_attributes_core->zoom = drawable_attributes_self->zoom; /* do not inerith the flip (this object, the uiable, doesn't flip) */ if ((d_call(uiable_attributes->background[index], m_drawable_normalize_scale, environment_attributes->reference_w, environment_attributes->reference_h, environment_attributes->camera_origin_x, environment_attributes->camera_origin_y, environment_attributes->camera_focus_x, environment_attributes->camera_focus_y, environment_attributes->current_w, environment_attributes->current_h, environment_attributes->zoom))) while (((int)d_call(uiable_attributes->background[index], m_drawable_draw, environment)) == d_drawable_return_continue); } d_cast_return(d_drawable_return_last); }
d_define_method(drawable, get_position)(struct s_object *self, double *x, double *y) { d_using(drawable); d_call(&(drawable_attributes->point_destination), m_point_get, x, y); return self; }
d_define_method(stream, write_string)(struct s_object *self, struct s_object *string, size_t *written) { size_t dimension; d_call(string, m_string_length, &dimension); return d_call(self, m_stream_write, (unsigned char *)d_string_cstring(string), dimension, written); }
d_define_method_override(label, draw)(struct s_object *self, struct s_object *environment) { d_using(label); struct s_drawable_attributes *drawable_attributes = d_cast(self, drawable); struct s_uiable_attributes *uiable_attributes = d_cast(self, uiable); struct s_environment_attributes *environment_attributes = d_cast(environment, environment); double position_x, position_y, dimension_w, dimension_h, center_x, center_y, width_factor, height_factor; int result = (intptr_t)d_call_owner(self, uiable, m_drawable_draw, environment); /* recall the father's draw method */ SDL_Rect source, destination; SDL_Point center; if (label_attributes->image) { d_call(&(drawable_attributes->point_normalized_destination), m_point_get, &position_x, &position_y); d_call(&(drawable_attributes->point_normalized_dimension), m_point_get, &dimension_w, &dimension_h); d_call(&(drawable_attributes->point_normalized_center), m_point_get, ¢er_x, ¢er_y); width_factor = (dimension_w/label_attributes->last_width); height_factor = (dimension_h/label_attributes->last_height); source.x = 0; source.y = 0; destination.x = (position_x + uiable_attributes->border_w); destination.y = (position_y + uiable_attributes->border_h); if (label_attributes->format == e_label_background_format_fixed) { source.w = d_math_min((label_attributes->last_width - (uiable_attributes->border_w * 2.0)), label_attributes->string_width); source.h = d_math_min((label_attributes->last_height - (uiable_attributes->border_h * 2.0)), label_attributes->string_height); switch (label_attributes->alignment_x) { case e_label_alignment_center: if ((source.x = d_math_max(((label_attributes->string_width-label_attributes->last_width)/2.0), 0)) == 0) destination.x = position_x + (((label_attributes->last_width - label_attributes->string_width)/2.0) * width_factor); break; case e_label_alignment_right: if ((source.x = d_math_max((label_attributes->string_width-label_attributes->last_width), 0)) == 0) destination.x = position_x + ((label_attributes->last_width - label_attributes->string_width) * width_factor); default: break; } switch (label_attributes->alignment_y) { case e_label_alignment_center: if ((source.y = d_math_max(((label_attributes->string_height-label_attributes->last_height)/2.0), 0)) == 0) destination.y = position_y + (((label_attributes->last_height - label_attributes->string_height)/2.0) * height_factor); break; case e_label_alignment_bottom: if ((source.y = d_math_max((label_attributes->string_height-label_attributes->last_height), 0)) == 0) destination.y = position_y + ((label_attributes->last_height - label_attributes->string_height) * height_factor); default: break; } } else if (label_attributes->format == e_label_background_format_adaptable) { source.w = label_attributes->string_width; source.h = label_attributes->string_height; } destination.w = source.w * width_factor; destination.h = source.h * height_factor; center.x = (position_x + center_x) - destination.x; center.y = (position_y + center_y) - destination.y; label_attributes->last_source = source; label_attributes->last_destination = destination; SDL_RenderCopyEx(environment_attributes->renderer, label_attributes->image, &source, &destination, drawable_attributes->angle, ¢er, (SDL_RendererFlip)drawable_attributes->flip); } d_cast_return(result); }
d_define_method_override(illuminable_bitmap, draw)(struct s_object *self, struct s_object *environment) { d_using(illuminable_bitmap); struct s_environment_attributes *environment_attributes = d_cast(environment, environment); struct s_drawable_attributes *drawable_attributes = d_cast(self, drawable); struct s_lights_emitter_description *lights_emitter; struct s_list affected_lights; struct s_object *result = d_call_owner(self, bitmap, m_drawable_draw, environment); /* recall the father's draw method */ double image_x, image_y, image_center_x, image_center_y, image_principal_point_x, image_principal_point_y, new_x, new_y, radians_rotation = -(drawable_attributes->angle * d_math_radians_conversion), radians_incident, cosine = cos(radians_rotation), sine = sin(radians_rotation), light_normalized_percentage[e_illuminable_bitmap_side_NULL], light_final_mask[e_illuminable_bitmap_side_NULL], local_factor, center_factor, center_factor_reduction; unsigned int index_side; if (illuminable_bitmap_attributes->lights) { memset(&(affected_lights), 0, sizeof(s_list)); for (index_side = 0; index_side < e_illuminable_bitmap_side_NULL; ++index_side) light_final_mask[index_side] = 0; d_call(self, m_drawable_get_scaled_position, &image_x, &image_y); d_call(self, m_drawable_get_scaled_center, &image_center_x, &image_center_y); d_call(self, m_drawable_get_scaled_principal_point, &image_principal_point_x, &image_principal_point_y); d_call(illuminable_bitmap_attributes->lights, m_lights_get_affecting_lights, self, &(affected_lights), environment); d_foreach(&(affected_lights), lights_emitter, struct s_lights_emitter_description) { for (index_side = 0; index_side < e_illuminable_bitmap_side_NULL; ++index_side) light_normalized_percentage[index_side] = 0; /* we need to re-calculate the coordinates of the light in respect of the angle generated by this image */ new_x = lights_emitter->position_x - (image_x + image_center_x); new_y = lights_emitter->position_y - (image_y + image_center_y); lights_emitter->position_x = (new_x * cosine) - (new_y * sine) + (image_x + image_center_x); lights_emitter->position_y = (new_x * sine) + (new_y * cosine) + (image_y + image_center_y); radians_incident = fmod(atan2(lights_emitter->position_y - image_principal_point_y, lights_emitter->position_x - image_principal_point_x), d_math_two_pi); /* we need to convert it to a positive angle */ if (radians_incident < 0) radians_incident = d_math_two_pi + radians_incident; center_factor_reduction = 0.0; switch (illuminable_bitmap_attributes->main_axis) { case e_illuminable_bitmap_axis_x: center_factor = 1.0 - (fabs(lights_emitter->position_x - image_principal_point_x) / ((image_principal_point_x + lights_emitter->radius) - image_x)); if ((intptr_t)d_call(&(drawable_attributes->square_collision_box), m_square_inside_coordinates, lights_emitter->position_x, lights_emitter->position_y)) center_factor_reduction = 1.0 - (fabs(lights_emitter->position_x - image_principal_point_x) / (image_principal_point_x - image_x)); break; case e_illuminable_bitmap_axis_y: center_factor = 1.0 - (fabs(lights_emitter->position_y - image_principal_point_y) / ((image_principal_point_y + lights_emitter->radius) - image_y)); if ((intptr_t)d_call(&(drawable_attributes->square_collision_box), m_square_inside_coordinates, lights_emitter->position_x, lights_emitter->position_y)) center_factor_reduction = 1.0 - (fabs(lights_emitter->position_y - image_principal_point_y) / (image_principal_point_y - image_y)); break; } light_normalized_percentage[e_illuminable_bitmap_side_front] = center_factor; if ((radians_incident >= 0) && (radians_incident < d_math_half_pi)) { light_normalized_percentage[e_illuminable_bitmap_side_bottom] = (radians_incident / d_math_half_pi) * (1.0 - center_factor_reduction); light_normalized_percentage[e_illuminable_bitmap_side_right] = (1.0 - (radians_incident / d_math_half_pi)) * (1.0 - center_factor_reduction); } else if ((radians_incident >= d_math_half_pi) && (radians_incident < d_math_pi)) { light_normalized_percentage[e_illuminable_bitmap_side_left] = ((radians_incident - d_math_half_pi) / d_math_half_pi) * (1.0 - center_factor_reduction); light_normalized_percentage[e_illuminable_bitmap_side_bottom] = (1.0 - ((radians_incident - d_math_half_pi) / d_math_half_pi)) * (1.0 - center_factor_reduction); } else if ((radians_incident >= d_math_pi) && (radians_incident < (d_math_pi + d_math_half_pi))) { light_normalized_percentage[e_illuminable_bitmap_side_top] = ((radians_incident - d_math_pi) / d_math_half_pi) * (1.0 - center_factor_reduction); light_normalized_percentage[e_illuminable_bitmap_side_left] = (1.0 - ((radians_incident - d_math_pi) / d_math_half_pi)) * (1.0 - center_factor_reduction); } else if ((radians_incident >= (d_math_pi + d_math_half_pi)) && (radians_incident < d_math_two_pi)) { light_normalized_percentage[e_illuminable_bitmap_side_right] = ((radians_incident - (d_math_pi + d_math_half_pi)) / d_math_half_pi) * (1.0 - center_factor_reduction); light_normalized_percentage[e_illuminable_bitmap_side_top] = (1.0 - ((radians_incident - (d_math_pi + d_math_half_pi)) / d_math_half_pi)) * (1.0 - center_factor_reduction); } for (index_side = 0; index_side < e_illuminable_bitmap_side_NULL; ++index_side) if ((local_factor = (light_normalized_percentage[index_side] * (((lights_emitter->radius - lights_emitter->distance) / lights_emitter->radius) * 255.0))) > 0) { /* now we have a factor that is proportional with the angle, with the distance and with the radius of the light. What we should do is to normalized * that value using the intensity and the penetration of the light into the */ if ((light_final_mask[index_side] += local_factor) > 255.0) light_final_mask[index_side] = 255.0; } } for (index_side = 0; index_side < e_illuminable_bitmap_side_NULL; ++index_side) { if ((light_final_mask[index_side] > 0) && (illuminable_bitmap_attributes->drawable_mask[index_side])) { /* we don't need to check the visibility because, if we are in this function, means that the visibility of the object has been already confirmed by the * called */ d_call(illuminable_bitmap_attributes->drawable_mask[index_side], m_drawable_set_maskRGB, (unsigned int)light_final_mask[index_side], (unsigned int)light_final_mask[index_side], (unsigned int)light_final_mask[index_side]); while (((intptr_t)d_call(illuminable_bitmap_attributes->drawable_mask[index_side], m_drawable_draw, environment)) == d_drawable_return_continue); } } /* clean the content */ while ((lights_emitter = (struct s_lights_emitter_description *)(affected_lights.head))) { f_list_delete(&(affected_lights), (struct s_list_node *)lights_emitter); d_free(lights_emitter); } }
d_define_method(emitter, embed_function)(struct s_object *self, const char *id, t_emitter_action action) { struct s_signal *signal; if ((signal = d_call(self, m_emitter_get, id))) signal->action = action; return (void *)signal; }