paysages : Added skybox in 3d explorer.
git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@341 b1fd45b6-86a6-48da-8261-f70d1f35bdcc
This commit is contained in:
parent
a3aa859f0c
commit
23c2056809
8 changed files with 239 additions and 29 deletions
|
@ -5,7 +5,7 @@
|
||||||
* New texture model (perpendicular displacement and thickness).
|
* New texture model (perpendicular displacement and thickness).
|
||||||
* Added clouds hardness to light.
|
* Added clouds hardness to light.
|
||||||
* Version management in saved files.
|
* Version management in saved files.
|
||||||
* Added ground texture and sun location in 3D explorer.
|
* Added ground texture and skybox in 3D explorer.
|
||||||
* 3D explorer now takes advantage of multiple CPU cores.
|
* 3D explorer now takes advantage of multiple CPU cores.
|
||||||
* Added sun halo control.
|
* Added sun halo control.
|
||||||
|
|
||||||
|
|
1
TODO
1
TODO
|
@ -6,6 +6,7 @@ Technology Preview 2 :
|
||||||
- Compute shadows only once for all textures at a same location.
|
- Compute shadows only once for all textures at a same location.
|
||||||
=> Add an intermediary light status (two pass lighting).
|
=> Add an intermediary light status (two pass lighting).
|
||||||
- Add layer sorting/naming.
|
- Add layer sorting/naming.
|
||||||
|
- Disable specular lighting in explorer (and everything camera dependent).
|
||||||
- Add logarithmic sliders for some float values.
|
- Add logarithmic sliders for some float values.
|
||||||
- Save GUI config (views, render params).
|
- Save GUI config (views, render params).
|
||||||
- Add an OSD ability on previews and use it for camera location and user landmarks.
|
- Add an OSD ability on previews and use it for camera location and user landmarks.
|
||||||
|
|
|
@ -47,7 +47,7 @@ bool BaseExplorerChunk::maintain()
|
||||||
{
|
{
|
||||||
if (_texture_current_size <= 1 || i % 2 != 0 || j % 2 != 0)
|
if (_texture_current_size <= 1 || i % 2 != 0 || j % 2 != 0)
|
||||||
{
|
{
|
||||||
Color color = getTextureColor((double)i / (double)(new_texture_size + 1), (double)j / (double)(new_texture_size + 1));
|
Color color = getTextureColor((double)i / (double)new_texture_size, 1.0 - (double)j / (double)new_texture_size);
|
||||||
new_image->setPixel(i, j, colorTo32BitBGRA(&color));
|
new_image->setPixel(i, j, colorTo32BitBGRA(&color));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
135
gui_qt/explorerchunksky.cpp
Normal file
135
gui_qt/explorerchunksky.cpp
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
#include "explorerchunksky.h"
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include "baseexplorerchunk.h"
|
||||||
|
#include "../lib_paysages/camera.h"
|
||||||
|
|
||||||
|
ExplorerChunkSky::ExplorerChunkSky(Renderer* renderer, SkyDefinition* sky, double size, SkyboxOrientation orientation) : BaseExplorerChunk(renderer)
|
||||||
|
{
|
||||||
|
_sky = sky;
|
||||||
|
_box_size = size;
|
||||||
|
_orientation = orientation;
|
||||||
|
|
||||||
|
setMaxTextureSize(256);
|
||||||
|
maintain();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExplorerChunkSky::onRenderEvent(QGLWidget* widget)
|
||||||
|
{
|
||||||
|
double size = _box_size;
|
||||||
|
Vector3 camera = renderer()->camera_location;
|
||||||
|
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
switch(_orientation)
|
||||||
|
{
|
||||||
|
case SKYBOX_NORTH:
|
||||||
|
glTexCoord2d(0.0, 0.0);
|
||||||
|
glVertex3d(camera.x - size, camera.y + size, camera.z - size);
|
||||||
|
glTexCoord2d(0.0, 1.0);
|
||||||
|
glVertex3d(camera.x - size, camera.y - size, camera.z - size);
|
||||||
|
glTexCoord2d(1.0, 1.0);
|
||||||
|
glVertex3d(camera.x + size, camera.y - size, camera.z - size);
|
||||||
|
glTexCoord2d(1.0, 0.0);
|
||||||
|
glVertex3d(camera.x + size, camera.y + size, camera.z - size);
|
||||||
|
break;
|
||||||
|
case SKYBOX_SOUTH:
|
||||||
|
glTexCoord2d(0.0, 0.0);
|
||||||
|
glVertex3d(camera.x + size, camera.y + size, camera.z + size);
|
||||||
|
glTexCoord2d(0.0, 1.0);
|
||||||
|
glVertex3d(camera.x + size, camera.y - size, camera.z + size);
|
||||||
|
glTexCoord2d(1.0, 1.0);
|
||||||
|
glVertex3d(camera.x - size, camera.y - size, camera.z + size);
|
||||||
|
glTexCoord2d(1.0, 0.0);
|
||||||
|
glVertex3d(camera.x - size, camera.y + size, camera.z + size);
|
||||||
|
break;
|
||||||
|
case SKYBOX_EAST:
|
||||||
|
glTexCoord2d(0.0, 0.0);
|
||||||
|
glVertex3d(camera.x + size, camera.y + size, camera.z - size);
|
||||||
|
glTexCoord2d(0.0, 1.0);
|
||||||
|
glVertex3d(camera.x + size, camera.y - size, camera.z - size);
|
||||||
|
glTexCoord2d(1.0, 1.0);
|
||||||
|
glVertex3d(camera.x + size, camera.y - size, camera.z + size);
|
||||||
|
glTexCoord2d(1.0, 0.0);
|
||||||
|
glVertex3d(camera.x + size, camera.y + size, camera.z + size);
|
||||||
|
break;
|
||||||
|
case SKYBOX_WEST:
|
||||||
|
glTexCoord2d(0.0, 0.0);
|
||||||
|
glVertex3d(camera.x - size, camera.y + size, camera.z + size);
|
||||||
|
glTexCoord2d(0.0, 1.0);
|
||||||
|
glVertex3d(camera.x - size, camera.y - size, camera.z + size);
|
||||||
|
glTexCoord2d(1.0, 1.0);
|
||||||
|
glVertex3d(camera.x - size, camera.y - size, camera.z - size);
|
||||||
|
glTexCoord2d(1.0, 0.0);
|
||||||
|
glVertex3d(camera.x - size, camera.y + size, camera.z - size);
|
||||||
|
break;
|
||||||
|
case SKYBOX_TOP:
|
||||||
|
glTexCoord2d(0.0, 0.0);
|
||||||
|
glVertex3d(camera.x - size, camera.y + size, camera.z + size);
|
||||||
|
glTexCoord2d(0.0, 1.0);
|
||||||
|
glVertex3d(camera.x - size, camera.y + size, camera.z - size);
|
||||||
|
glTexCoord2d(1.0, 1.0);
|
||||||
|
glVertex3d(camera.x + size, camera.y + size, camera.z - size);
|
||||||
|
glTexCoord2d(1.0, 0.0);
|
||||||
|
glVertex3d(camera.x + size, camera.y + size, camera.z + size);
|
||||||
|
break;
|
||||||
|
case SKYBOX_BOTTOM:
|
||||||
|
glTexCoord2d(0.0, 0.0);
|
||||||
|
glVertex3d(camera.x - size, camera.y - size, camera.z - size);
|
||||||
|
glTexCoord2d(0.0, 1.0);
|
||||||
|
glVertex3d(camera.x - size, camera.y - size, camera.z + size);
|
||||||
|
glTexCoord2d(1.0, 1.0);
|
||||||
|
glVertex3d(camera.x + size, camera.y - size, camera.z + size);
|
||||||
|
glTexCoord2d(1.0, 0.0);
|
||||||
|
glVertex3d(camera.x + size, camera.y - size, camera.z - size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
glEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
double ExplorerChunkSky::getDisplayedSizeHint(CameraDefinition* camera)
|
||||||
|
{
|
||||||
|
return 1000.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Color ExplorerChunkSky::getTextureColor(double x, double y)
|
||||||
|
{
|
||||||
|
Vector3 location;
|
||||||
|
|
||||||
|
x -= 0.5;
|
||||||
|
y -= 0.5;
|
||||||
|
|
||||||
|
switch(_orientation)
|
||||||
|
{
|
||||||
|
case SKYBOX_NORTH:
|
||||||
|
location.x = x;
|
||||||
|
location.y = -y;
|
||||||
|
location.z = -0.5;
|
||||||
|
break;
|
||||||
|
case SKYBOX_SOUTH:
|
||||||
|
location.x = -x;
|
||||||
|
location.y = -y;
|
||||||
|
location.z = 0.5;
|
||||||
|
break;
|
||||||
|
case SKYBOX_EAST:
|
||||||
|
location.x = 0.5;
|
||||||
|
location.y = -y;
|
||||||
|
location.z = x;
|
||||||
|
break;
|
||||||
|
case SKYBOX_WEST:
|
||||||
|
location.x = -0.5;
|
||||||
|
location.y = -y;
|
||||||
|
location.z = -x;
|
||||||
|
break;
|
||||||
|
case SKYBOX_TOP:
|
||||||
|
location.x = x;
|
||||||
|
location.y = 0.5;
|
||||||
|
location.z = -y;
|
||||||
|
break;
|
||||||
|
case SKYBOX_BOTTOM:
|
||||||
|
location.x = x;
|
||||||
|
location.y = -0.5;
|
||||||
|
location.z = y;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return skyGetColor(_sky, renderer(), VECTOR_ZERO, v3Normalize(location));
|
||||||
|
}
|
35
gui_qt/explorerchunksky.h
Normal file
35
gui_qt/explorerchunksky.h
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
#ifndef _PAYSAGES_QT_EXPLORERCHUNKSKY_H_
|
||||||
|
#define _PAYSAGES_QT_EXPLORERCHUNKSKY_H_
|
||||||
|
|
||||||
|
#include "baseexplorerchunk.h"
|
||||||
|
#include "../lib_paysages/renderer.h"
|
||||||
|
#include "../lib_paysages/euclid.h"
|
||||||
|
#include "../lib_paysages/sky.h"
|
||||||
|
|
||||||
|
enum SkyboxOrientation
|
||||||
|
{
|
||||||
|
SKYBOX_NORTH,
|
||||||
|
SKYBOX_SOUTH,
|
||||||
|
SKYBOX_WEST,
|
||||||
|
SKYBOX_EAST,
|
||||||
|
SKYBOX_TOP,
|
||||||
|
SKYBOX_BOTTOM
|
||||||
|
};
|
||||||
|
|
||||||
|
class ExplorerChunkSky:public BaseExplorerChunk
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ExplorerChunkSky(Renderer* renderer, SkyDefinition* sky, double size, SkyboxOrientation orientation);
|
||||||
|
|
||||||
|
void onRenderEvent(QGLWidget* widget);
|
||||||
|
double getDisplayedSizeHint(CameraDefinition* camera);
|
||||||
|
Color getTextureColor(double x, double y);
|
||||||
|
|
||||||
|
private:
|
||||||
|
SkyDefinition* _sky;
|
||||||
|
SkyboxOrientation _orientation;
|
||||||
|
double _box_size;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -112,9 +112,9 @@ void ExplorerChunkTerrain::onRenderEvent(QGLWidget* widget)
|
||||||
glBegin(GL_QUAD_STRIP);
|
glBegin(GL_QUAD_STRIP);
|
||||||
for (int i = 0; i <= _tessellation_max_size; i += tessellation_inc)
|
for (int i = 0; i <= _tessellation_max_size; i += tessellation_inc)
|
||||||
{
|
{
|
||||||
glTexCoord2d(tsize * (double)i, 1.0 - tsize * (double)j);
|
glTexCoord2d(tsize * (double)i, tsize * (double)j);
|
||||||
glVertex3d(_startx + _tessellation_step * (double)i, _tessellation[j * (_tessellation_max_size + 1) + i], _startz + _tessellation_step * (double)j);
|
glVertex3d(_startx + _tessellation_step * (double)i, _tessellation[j * (_tessellation_max_size + 1) + i], _startz + _tessellation_step * (double)j);
|
||||||
glTexCoord2d(tsize * (double)i, 1.0 - tsize * (double)(j + tessellation_inc));
|
glTexCoord2d(tsize * (double)i, tsize * (double)(j + tessellation_inc));
|
||||||
glVertex3d(_startx + _tessellation_step * (double)i, _tessellation[(j + tessellation_inc) * (_tessellation_max_size + 1) + i], _startz + _tessellation_step * (double)(j + tessellation_inc));
|
glVertex3d(_startx + _tessellation_step * (double)i, _tessellation[(j + tessellation_inc) * (_tessellation_max_size + 1) + i], _startz + _tessellation_step * (double)(j + tessellation_inc));
|
||||||
}
|
}
|
||||||
glEnd();
|
glEnd();
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
#include "../lib_paysages/scenery.h"
|
#include "../lib_paysages/scenery.h"
|
||||||
#include "../lib_paysages/euclid.h"
|
#include "../lib_paysages/euclid.h"
|
||||||
#include "explorerchunkterrain.h"
|
#include "explorerchunkterrain.h"
|
||||||
|
#include "explorerchunksky.h"
|
||||||
|
#include "tools.h"
|
||||||
|
|
||||||
class ChunkMaintenanceThread:public QThread
|
class ChunkMaintenanceThread:public QThread
|
||||||
{
|
{
|
||||||
|
@ -99,6 +101,7 @@ WidgetExplorer::WidgetExplorer(QWidget *parent, CameraDefinition* camera):
|
||||||
|
|
||||||
_updated = false;
|
_updated = false;
|
||||||
|
|
||||||
|
// Add terrain
|
||||||
int chunks = 20;
|
int chunks = 20;
|
||||||
double size = 200.0;
|
double size = 200.0;
|
||||||
double chunksize = size / (double)chunks;
|
double chunksize = size / (double)chunks;
|
||||||
|
@ -113,6 +116,14 @@ WidgetExplorer::WidgetExplorer(QWidget *parent, CameraDefinition* camera):
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add skybox
|
||||||
|
for (int orientation = 0; orientation < 6; orientation++)
|
||||||
|
{
|
||||||
|
ExplorerChunkSky* chunk = new ExplorerChunkSky(&_renderer, &_sky, 500.0, (SkyboxOrientation)orientation);
|
||||||
|
_chunks.append(chunk);
|
||||||
|
_updateQueue.append(chunk);
|
||||||
|
}
|
||||||
|
|
||||||
startThreads();
|
startThreads();
|
||||||
startTimer(500);
|
startTimer(500);
|
||||||
|
|
||||||
|
@ -400,6 +411,7 @@ void WidgetExplorer::resizeGL(int w, int h)
|
||||||
|
|
||||||
void WidgetExplorer::paintGL()
|
void WidgetExplorer::paintGL()
|
||||||
{
|
{
|
||||||
|
GLenum error_code;
|
||||||
QTime start_time;
|
QTime start_time;
|
||||||
double frame_time;
|
double frame_time;
|
||||||
|
|
||||||
|
@ -409,6 +421,7 @@ void WidgetExplorer::paintGL()
|
||||||
}
|
}
|
||||||
|
|
||||||
cameraValidateDefinition(&_current_camera, 1);
|
cameraValidateDefinition(&_current_camera, 1);
|
||||||
|
_renderer.camera_location = _current_camera.location;
|
||||||
|
|
||||||
start_time = QTime::currentTime();
|
start_time = QTime::currentTime();
|
||||||
|
|
||||||
|
@ -421,20 +434,7 @@ void WidgetExplorer::paintGL()
|
||||||
glClearColor(zenith_color.r, zenith_color.g, zenith_color.b, 0.0);
|
glClearColor(zenith_color.r, zenith_color.g, zenith_color.b, 0.0);
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
// Render sun
|
|
||||||
Vector3 sun_location = v3Add(_current_camera.location, v3Scale(skyGetSunDirection(&_sky), 500.0));
|
|
||||||
Color sun_color = skyGetSunColor(&_sky);
|
|
||||||
glDisable(GL_TEXTURE);
|
|
||||||
glDisable(GL_TEXTURE_2D);
|
|
||||||
glColor3f(sun_color.r, sun_color.g, sun_color.b);
|
|
||||||
glPointSize(15.0 * _sky.sun_radius / 0.02);
|
|
||||||
glEnable(GL_POINT_SMOOTH);
|
|
||||||
glBegin(GL_POINTS);
|
|
||||||
glVertex3f(sun_location.x, sun_location.y, sun_location.z);
|
|
||||||
glEnd();
|
|
||||||
|
|
||||||
// Render water
|
// Render water
|
||||||
glDisable(GL_TEXTURE);
|
|
||||||
glDisable(GL_TEXTURE_2D);
|
glDisable(GL_TEXTURE_2D);
|
||||||
glColor3f(_water.material.base.r, _water.material.base.g, _water.material.base.b);
|
glColor3f(_water.material.base.r, _water.material.base.g, _water.material.base.b);
|
||||||
glBegin(GL_QUADS);
|
glBegin(GL_QUADS);
|
||||||
|
@ -444,8 +444,7 @@ void WidgetExplorer::paintGL()
|
||||||
glVertex3f(_current_camera.location.x + 500.0, _water.height, _current_camera.location.z - 500.0);
|
glVertex3f(_current_camera.location.x + 500.0, _water.height, _current_camera.location.z - 500.0);
|
||||||
glEnd();
|
glEnd();
|
||||||
|
|
||||||
// Render terrain chunks
|
// Render chunks
|
||||||
glEnable(GL_TEXTURE);
|
|
||||||
glEnable(GL_TEXTURE_2D);
|
glEnable(GL_TEXTURE_2D);
|
||||||
for (int i = 0; i < _chunks.count(); i++)
|
for (int i = 0; i < _chunks.count(); i++)
|
||||||
{
|
{
|
||||||
|
@ -466,4 +465,9 @@ void WidgetExplorer::paintGL()
|
||||||
{
|
{
|
||||||
_quality++;
|
_quality++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while ((error_code = glGetError()) != GL_NO_ERROR)
|
||||||
|
{
|
||||||
|
logDebug(QString("[OpenGL] ERROR : ") + (const char*)gluErrorString(error_code));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,6 +121,46 @@ Right click on a point to delete it.</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
|
<context>
|
||||||
|
<name>DialogExplorer</name>
|
||||||
|
<message>
|
||||||
|
<location filename="../gui_qt/dialogexplorer.cpp" line="14"/>
|
||||||
|
<source>Paysages 3D - Explore</source>
|
||||||
|
<translation type="unfinished">Paysages 3D - Exploration</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../gui_qt/dialogexplorer.cpp" line="24"/>
|
||||||
|
<source>COMMANDS
|
||||||
|
|
||||||
|
Left click : Look around
|
||||||
|
Right click : Pan (adjust framing)
|
||||||
|
Wheel : Move forward/backward
|
||||||
|
Hold SHIFT : Faster
|
||||||
|
Hold CTRL : Slower</source>
|
||||||
|
<translation type="unfinished">COMMANDES
|
||||||
|
|
||||||
|
Clic gauche : Regarder autour
|
||||||
|
Clic droit : Déplacer le cadrage
|
||||||
|
Molette : Avancer/reculer
|
||||||
|
Maintenir Maj : Plus rapide
|
||||||
|
Maintenir Ctrl : Plus lent</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../gui_qt/dialogexplorer.cpp" line="26"/>
|
||||||
|
<source>Reset camera</source>
|
||||||
|
<translation type="unfinished">Revenir au point de vue initial</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../gui_qt/dialogexplorer.cpp" line="32"/>
|
||||||
|
<source>Validate as render camera</source>
|
||||||
|
<translation type="unfinished">Choisir comme caméra de rendu</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../gui_qt/dialogexplorer.cpp" line="37"/>
|
||||||
|
<source>Close</source>
|
||||||
|
<translation type="unfinished">Fermer</translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>DialogMaterial</name>
|
<name>DialogMaterial</name>
|
||||||
<message>
|
<message>
|
||||||
|
@ -218,12 +258,10 @@ Right click on a point to delete it.</source>
|
||||||
<context>
|
<context>
|
||||||
<name>DialogWanderer</name>
|
<name>DialogWanderer</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../gui_qt/dialogexplorer.cpp" line="14"/>
|
|
||||||
<source>Paysages 3D - Explore</source>
|
<source>Paysages 3D - Explore</source>
|
||||||
<translation>Paysages 3D - Exploration</translation>
|
<translation type="obsolete">Paysages 3D - Exploration</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../gui_qt/dialogexplorer.cpp" line="24"/>
|
|
||||||
<source>COMMANDS
|
<source>COMMANDS
|
||||||
|
|
||||||
Left click : Look around
|
Left click : Look around
|
||||||
|
@ -231,7 +269,7 @@ Right click : Pan (adjust framing)
|
||||||
Wheel : Move forward/backward
|
Wheel : Move forward/backward
|
||||||
Hold SHIFT : Faster
|
Hold SHIFT : Faster
|
||||||
Hold CTRL : Slower</source>
|
Hold CTRL : Slower</source>
|
||||||
<translation>COMMANDES
|
<translation type="obsolete">COMMANDES
|
||||||
|
|
||||||
Clic gauche : Regarder autour
|
Clic gauche : Regarder autour
|
||||||
Clic droit : Déplacer le cadrage
|
Clic droit : Déplacer le cadrage
|
||||||
|
@ -256,19 +294,16 @@ Maintenir MAJ : Plus lent
|
||||||
Maintenir Ctrl : Plus rapide</translation>
|
Maintenir Ctrl : Plus rapide</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../gui_qt/dialogexplorer.cpp" line="26"/>
|
|
||||||
<source>Reset camera</source>
|
<source>Reset camera</source>
|
||||||
<translation>Revenir au point de vue initial</translation>
|
<translation type="obsolete">Revenir au point de vue initial</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../gui_qt/dialogexplorer.cpp" line="32"/>
|
|
||||||
<source>Validate as render camera</source>
|
<source>Validate as render camera</source>
|
||||||
<translation>Choisir comme caméra de rendu</translation>
|
<translation type="obsolete">Choisir comme caméra de rendu</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../gui_qt/dialogexplorer.cpp" line="37"/>
|
|
||||||
<source>Close</source>
|
<source>Close</source>
|
||||||
<translation>Fermer</translation>
|
<translation type="obsolete">Fermer</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
|
|
Loading…
Reference in a new issue