branches/micko/src/emu/guiengine.c
r23973 | r23974 | |
47 | 47 | |
48 | 48 | class ShellSystemInterface : public Rocket::Core::SystemInterface |
49 | 49 | { |
| 50 | private: |
| 51 | // internal state |
| 52 | running_machine & m_machine; // reference to our machine |
| 53 | |
50 | 54 | public: |
| 55 | ShellSystemInterface(running_machine &machine) |
| 56 | : m_machine(machine) |
| 57 | { |
| 58 | } |
| 59 | |
| 60 | // getters |
| 61 | running_machine &machine() const { return m_machine; } |
| 62 | |
51 | 63 | /// Get the number of seconds elapsed since the start of the application |
52 | 64 | /// @returns Seconds elapsed |
53 | | virtual float GetElapsedTime() { return 0; } |
| 65 | virtual float GetElapsedTime() { return machine().time().as_double(); } |
54 | 66 | }; |
55 | 67 | |
56 | | class ShellRenderInterfaceOpenGL : public Rocket::Core::RenderInterface |
| 68 | #define UI_LINE_WIDTH (1.0f / 500.0f) |
| 69 | #define UI_BORDER_COLOR MAKE_ARGB(0xff,0xff,0xff,0xff) |
| 70 | |
| 71 | class ShellRenderInterfaceSystem : public Rocket::Core::RenderInterface |
57 | 72 | { |
| 73 | private: |
| 74 | // internal state |
| 75 | running_machine & m_machine; // reference to our machine |
| 76 | |
58 | 77 | public: |
59 | | ShellRenderInterfaceOpenGL() |
| 78 | ShellRenderInterfaceSystem(running_machine &machine) |
| 79 | : m_machine(machine) |
60 | 80 | { |
61 | 81 | } |
| 82 | |
| 83 | // getters |
| 84 | running_machine &machine() const { return m_machine; } |
62 | 85 | |
63 | 86 | /// Called by Rocket when it wants to render geometry that it does not wish to optimise. |
64 | 87 | virtual void RenderGeometry(Rocket::Core::Vertex* vertices, int num_vertices, int* indices, int num_indices, Rocket::Core::TextureHandle texture, const Rocket::Core::Vector2f& translation) |
65 | 88 | { |
| 89 | //printf("Vertex\n"); |
| 90 | for (int i = 0; i < num_vertices; ++i) |
| 91 | { |
| 92 | //printf("[%d] %f,%f \n",i,vertices[i].position.x,vertices[i].position.y); |
| 93 | |
| 94 | |
| 95 | //d3d9_vertices[i].colour = D3DCOLOR_RGBA(vertices[i].colour.red, vertices[i].colour.green, vertices[i].colour.blue, vertices[i].colour.alpha); |
| 96 | |
| 97 | //d3d9_vertices[i].u = vertices[i].tex_coord[0]; |
| 98 | //d3d9_vertices[i].v = vertices[i].tex_coord[1]; |
| 99 | //container->add_line(bar_left, bar_top, bar_left + bar_width, bar_top, UI_LINE_WIDTH, UI_BORDER_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); |
| 100 | } |
| 101 | //printf("indices\n"); |
| 102 | for (int i = 0; i < num_indices/3; i++) |
| 103 | { |
| 104 | //printf("[%d] %d \n",i,indices[i]); |
| 105 | machine().render().ui_container().add_line((vertices[i*3+0].position.x+translation.x)/1024,(vertices[i*3+0].position.y+translation.y)/768, (vertices[i*3+1].position.x+translation.x)/1024,(vertices[i*3+1].position.y+translation.y)/768, UI_LINE_WIDTH, UI_BORDER_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); |
| 106 | machine().render().ui_container().add_line((vertices[i*3+1].position.x+translation.x)/1024,(vertices[i*3+1].position.y+translation.y)/768, (vertices[i*3+2].position.x+translation.x)/1024,(vertices[i*3+2].position.y+translation.y)/768, UI_LINE_WIDTH, UI_BORDER_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); |
| 107 | machine().render().ui_container().add_line((vertices[i*3+2].position.x+translation.x)/1024,(vertices[i*3+2].position.y+translation.y)/768, (vertices[i*3+0].position.x+translation.x)/1024,(vertices[i*3+0].position.y+translation.y)/768, UI_LINE_WIDTH, UI_BORDER_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); |
| 108 | |
| 109 | } |
66 | 110 | } |
67 | 111 | |
68 | 112 | /// Called by Rocket when it wants to compile geometry it believes will be static for the forseeable future. |
r23973 | r23974 | |
83 | 127 | |
84 | 128 | /// Called by Rocket when it wants to enable or disable scissoring to clip content. |
85 | 129 | virtual void EnableScissorRegion(bool enable) |
86 | | { |
| 130 | { |
87 | 131 | } |
88 | 132 | /// Called by Rocket when it wants to change the scissor region. |
89 | 133 | virtual void SetScissorRegion(int x, int y, int width, int height) |
90 | 134 | { |
91 | 135 | } |
92 | 136 | |
| 137 | |
| 138 | // Set to byte packing, or the compiler will expand our struct, which means it won't read correctly from file |
| 139 | #pragma pack(1) |
| 140 | struct TGAHeader |
| 141 | { |
| 142 | char idLength; |
| 143 | char colourMapType; |
| 144 | char dataType; |
| 145 | short int colourMapOrigin; |
| 146 | short int colourMapLength; |
| 147 | char colourMapDepth; |
| 148 | short int xOrigin; |
| 149 | short int yOrigin; |
| 150 | short int width; |
| 151 | short int height; |
| 152 | char bitsPerPixel; |
| 153 | char imageDescriptor; |
| 154 | }; |
| 155 | // Restore packing |
| 156 | #pragma pack() |
| 157 | |
93 | 158 | /// Called by Rocket when a texture is required by the library. |
94 | 159 | virtual bool LoadTexture(Rocket::Core::TextureHandle& texture_handle, Rocket::Core::Vector2i& texture_dimensions, const Rocket::Core::String& source) |
95 | 160 | { |
96 | | return true; |
| 161 | emu_file file("", OPEN_FLAG_READ); |
| 162 | file_error filerr = file.open(source.CString()); |
| 163 | if(filerr != FILERR_NONE) |
| 164 | { |
| 165 | return false; |
| 166 | } |
| 167 | |
| 168 | file.seek(0, SEEK_END); |
| 169 | size_t buffer_size = file.tell(); |
| 170 | file.seek(0, SEEK_SET); |
| 171 | |
| 172 | char* buffer = new char[buffer_size]; |
| 173 | file.read(buffer, buffer_size); |
| 174 | file.close(); |
| 175 | |
| 176 | TGAHeader header; |
| 177 | memcpy(&header, buffer, sizeof(TGAHeader)); |
| 178 | |
| 179 | int color_mode = header.bitsPerPixel / 8; |
| 180 | int image_size = header.width * header.height * 4; // We always make 32bit textures |
| 181 | |
| 182 | if (header.dataType != 2) |
| 183 | { |
| 184 | Rocket::Core::Log::Message(Rocket::Core::Log::LT_ERROR, "Only 24/32bit uncompressed TGAs are supported."); |
| 185 | return false; |
| 186 | } |
| 187 | |
| 188 | // Ensure we have at least 3 colors |
| 189 | if (color_mode < 3) |
| 190 | { |
| 191 | Rocket::Core::Log::Message(Rocket::Core::Log::LT_ERROR, "Only 24 and 32bit textures are supported"); |
| 192 | return false; |
| 193 | } |
| 194 | |
| 195 | const char* image_src = buffer + sizeof(TGAHeader); |
| 196 | unsigned char* image_dest = new unsigned char[image_size]; |
| 197 | |
| 198 | // Targa is BGR, swap to RGB and flip Y axis |
| 199 | for (long y = 0; y < header.height; y++) |
| 200 | { |
| 201 | long read_index = y * header.width * color_mode; |
| 202 | long write_index = ((header.imageDescriptor & 32) != 0) ? read_index : (header.height - y - 1) * header.width * color_mode; |
| 203 | for (long x = 0; x < header.width; x++) |
| 204 | { |
| 205 | image_dest[write_index] = image_src[read_index+2]; |
| 206 | image_dest[write_index+1] = image_src[read_index+1]; |
| 207 | image_dest[write_index+2] = image_src[read_index]; |
| 208 | if (color_mode == 4) |
| 209 | image_dest[write_index+3] = image_src[read_index+3]; |
| 210 | else |
| 211 | image_dest[write_index+3] = 255; |
| 212 | |
| 213 | write_index += 4; |
| 214 | read_index += color_mode; |
| 215 | } |
| 216 | } |
| 217 | |
| 218 | texture_dimensions.x = header.width; |
| 219 | texture_dimensions.y = header.height; |
| 220 | |
| 221 | bool success = GenerateTexture(texture_handle, image_dest, texture_dimensions); |
| 222 | |
| 223 | delete [] image_dest; |
| 224 | delete [] buffer; |
| 225 | |
| 226 | return success; |
97 | 227 | } |
98 | 228 | /// Called by Rocket when a texture is required to be built from an internally-generated sequence of pixels. |
99 | 229 | virtual bool GenerateTexture(Rocket::Core::TextureHandle& texture_handle, const Rocket::Core::byte* source, const Rocket::Core::Vector2i& source_dimensions) |
r23973 | r23974 | |
106 | 236 | } |
107 | 237 | }; |
108 | 238 | |
109 | | ShellRenderInterfaceOpenGL opengl_renderer; |
110 | | ShellSystemInterface system_interface; |
| 239 | ShellRenderInterfaceSystem *system_renderer = NULL; |
| 240 | ShellSystemInterface *system_interface = NULL; |
111 | 241 | Rocket::Core::Context* context = NULL; |
112 | 242 | |
113 | 243 | //************************************************************************** |
r23973 | r23974 | |
140 | 270 | void gui_engine::initialize() |
141 | 271 | { |
142 | 272 | // Rocket initialisation. |
143 | | Rocket::Core::SetRenderInterface(&opengl_renderer); |
| 273 | system_renderer = new ShellRenderInterfaceSystem(machine()); |
| 274 | Rocket::Core::SetRenderInterface(system_renderer); |
144 | 275 | |
145 | | Rocket::Core::SetSystemInterface(&system_interface); |
| 276 | system_interface = new ShellSystemInterface(machine()); |
| 277 | Rocket::Core::SetSystemInterface(system_interface); |
146 | 278 | |
147 | 279 | Rocket::Core::Initialise(); |
148 | 280 | // Initialise the Rocket Controls library. |
149 | 281 | Rocket::Controls::Initialise(); |
150 | 282 | |
151 | 283 | // Create the main Rocket context and set it on the shell's input layer. |
152 | | context = Rocket::Core::CreateContext("main", Rocket::Core::Vector2i(1920, 1080)); |
| 284 | context = Rocket::Core::CreateContext("main", Rocket::Core::Vector2i(1024, 768)); |
153 | 285 | if (context == NULL) |
154 | 286 | { |
155 | 287 | Rocket::Core::Shutdown(); |
r23973 | r23974 | |
178 | 310 | |
179 | 311 | void gui_engine::update() |
180 | 312 | { |
| 313 | /* always start clean */ |
| 314 | machine().render().ui_container().empty(); |
| 315 | |
181 | 316 | context->Update(); |
182 | 317 | context->Render(); |
183 | 318 | } |
| 319 | |
| 320 | |
| 321 | void gui_engine::loadFonts(const char* directory) |
| 322 | { |
| 323 | Rocket::Core::String font_names[4]; |
| 324 | font_names[0] = "Delicious-Roman.otf"; |
| 325 | font_names[1] = "Delicious-Italic.otf"; |
| 326 | font_names[2] = "Delicious-Bold.otf"; |
| 327 | font_names[3] = "Delicious-BoldItalic.otf"; |
| 328 | |
| 329 | for (int i = 0; i < sizeof(font_names) / sizeof(Rocket::Core::String); i++) |
| 330 | { |
| 331 | Rocket::Core::FontDatabase::LoadFontFace(Rocket::Core::String(directory) + font_names[i]); |
| 332 | } |
| 333 | } |
| 334 | |
| 335 | void gui_engine::loadDocument(const char *filename) |
| 336 | { |
| 337 | Rocket::Core::ElementDocument* document = context->LoadDocument(filename); |
| 338 | if (document != NULL) |
| 339 | { |
| 340 | document->Show(); |
| 341 | document->RemoveReference(); |
| 342 | } |
| 343 | } |