Merge branch 'master' into NDK

Former-commit-id: f118c029ca94296495957816f910d412ae8a56f2
This commit is contained in:
Lynix 2015-03-18 20:44:52 +01:00
commit 5c3720feb1
66 changed files with 1430 additions and 599 deletions

10
.gitignore vendored
View File

@ -18,13 +18,23 @@ SDK/lib/NazaraSDK*.so
# CodeLite # CodeLite
*.project *.project
# Visual Studio
*.filters
*.vcxproj
*.tlog
*.sln
*.vcxprojResolveAssemblyReference.cache
*.exp
# Compiled Object files # Compiled Object files
*.slo *.slo
*.lo *.lo
*.o *.o
*.obj
# Compiled Dynamic libraries # Compiled Dynamic libraries
*.so *.so
*.lib
# Compiled Static libraries # Compiled Static libraries
*.lai *.lai

View File

@ -0,0 +1,239 @@
function PrintTable ( t, indent, done )
done = done or {}
indent = indent or 0
local txt = {}
for key, value in pairs (t) do
table.insert(txt, string.rep (" ", indent))
if (type(value) == "table" and not done[value]) then
done [value] = true
table.insert(txt, tostring(key) .. ":" .. "\n")
table.insert(txt, PrintTable (value, indent + 2, done))
else
table.insert(txt, tostring (key) .. "\t=\t" )
table.insert(txt, tostring(value) .. "\n" )
end
end
return table.concat(txt)
end
Feature = {}
-- Tables de vérité
local andTable =
{
{0,0},
{0,1},
}
local orTable =
{
{0,1},
{1,1},
}
local xorTable =
{
{0,1},
{1,0},
}
local bitFunc = function (a, b, truthTable)
local power = 1
local c = 0
while (a > 0 or b > 0) do
c = c + (truthTable[(a % 2)+1][(b % 2)+1] * power)
a = math.floor(a/2)
b = math.floor(b/2)
power = power * 2
end
return c
end
function Feature.AND(a, b)
return bitFunc(a, b, andTable)
end
function Feature.OR(a, b)
return bitFunc(a, b, orTable)
end
function Feature.XOR(a, b)
return bitFunc(a, b, xorTable)
end
Feature.NotApplicable = 0
Feature.Windows = 2 ^ 0
Feature.Linux = 2 ^ 1
Feature.MacOSX = 2 ^ 2
Feature.RaspberryPi = 2 ^ 3
Feature.POSIX = Feature.Linux + Feature.MacOSX + Feature.RaspberryPi
function Feature.CompleteData(tab, requiredPortability)
if (not requiredPortability) then
assert(tab.RequiredPortability)
requiredPortability = tab.RequiredPortability
elseif (tab.RequiredPortability) then
requiredPortability = Feature.OR(requiredPortability, tab.RequiredPortability)
end
tab.RequiredPortability = requiredPortability
if (not tab.Portability) then
tab.Portability = Feature.NotApplicable
end
if (tab.Features) then
local acc = 0
for k,v in pairs(tab.Features) do
if (type(v) == "string") then
v = {Title = v}
tab.Features[k] = v
end
Feature.CompleteData(v, requiredPortability)
v.Progress = v.Progress or 100
acc = acc + v.Progress
end
tab.Progress = acc/#tab.Features
end
end
function Feature.Generate()
local files = os.matchfiles("scripts/features/*.lua")
local modules = {}
for k, filePath in pairs(files) do
local moduleName = filePath:match(".*/(.*).lua")
local data = dofile(filePath)
Feature.CompleteData(data)
modules[moduleName] = data
end
local content = {}
local contentType =
{
["(%s*)%%MODULELIST%%"] = Feature.GenerateModuleList,
["(%s*)%%MODULEDESCRIPTION%%"] = Feature.GenerateModuleDescriptions,
["(%s*)%%DATE%%"] = function (dontcare, space, content)
table.insert(content, string.format("%s%s", space, os.date("%d/%m/%Y")))
end,
}
local index = io.open("scripts/features/index_template.html")
for line in index:lines() do
local matched = false
for k,v in pairs(contentType) do
local space = line:match(k)
if (space) then
matched = true
v(modules, space, content)
break
end
end
if (not matched) then
table.insert(content, line)
end
end
io.open("scripts/features/index.html", "w+"):write(table.concat(content, "\n"))
end
function Feature.Interpolate(from, to, p)
return from + (to - from)*p
end
function Feature.ComputeColor(progress)
local stable = {0, 200, 0}
local partial = {255, 127, 0}
local unusable = {255, 0, 0}
local a, b, p
if (progress < 20) then
a = unusable
b = partial
p = progress/20.0
else
a = partial
b = stable
p = math.min(20 * 1.020321705^(progress - 20), 100.0)/100.0 -- Je me complique certainement la vie pour ce qui est d'avoir une interpolation exponentielle, mais ça remonte tout ça ...
end
local color = {nil, nil, nil}
for i = 1, 3 do
color[i] = Feature.Interpolate(a[i], b[i], p)
end
return color
end
function Feature.GenerateModuleList(modules, space, content)
for k,v in pairs(modules) do
local c = Feature.ComputeColor(v.Progress)
table.insert(content, string.format([[%s<tr>]], space))
table.insert(content, string.format([[%s <td><a href="#%s">%s</a></td>]], space, k, v.Title))
table.insert(content, string.format([[%s <td style="color: rgb(%d, %d, %d);">%d%%</td>]], space, c[1], c[2], c[3], v.Progress))
table.insert(content, string.format([[%s</tr>]], space))
end
end
function Feature.GenerateModuleDescriptions(modules, space, content)
for k,v in pairs(modules) do
table.insert(content, string.format([[%s<div class="module">]], space))
table.insert(content, string.format([[%s <hr />]], space, k, v.Title))
table.insert(content, string.format([[%s <span id="%s" class="modulename">%s (%s) : %d%%</span>]], space, k, v.Title, v.LibName, math.floor(v.Progress)))
table.insert(content, string.format([[%s <h4>Fonctionnalités:</h4>]], space))
Feature.GenerateFeatureList(v.Features, space .. "\t\t", content)
table.insert(content, string.format([[%s</div>]], space))
end
end
function Feature.GenerateFeatureList(featureTable, space, content)
table.insert(content, string.format("%s<ul>", space))
for k,v in pairs(featureTable) do
local progress = v.Progress
local c = Feature.ComputeColor(progress)
local desc = (progress == 100) and "" or string.format(" (%d%%)", math.floor(progress))
table.insert(content, string.format("%s <li>", space))
table.insert(content, string.format([[%s <span style="color: rgb(%d, %d, %d);">%s%s</span>]], space, c[1], c[2], c[3], v.Title, desc))
if (v.Description) then
table.insert(content, string.format([[%s <br><span class="description">%s</span>]], space, v.Description))
end
if (v.Features) then
Feature.GenerateFeatureList(v.Features, space .. "\t\t\t", content)
end
if (v.Note) then
table.insert(content, string.format([[%s <br><span class="note">Note: <span class="notedesc">%s</span></span>]], space, v.Note))
end
if (v.Portability ~= Feature.NotApplicable and Feature.AND(v.Portability, v.RequiredPortability) ~= v.RequiredPortability) then
table.insert(content, string.format([[%s <br><span class="portability">Il manque une implémentation sur au moins un des OS supportés</span>]], space))
end
table.insert(content, string.format("%s </li>", space))
end
table.insert(content, string.format("%s</ul>", space))
end
newaction
{
trigger = "generatefeatures",
description = "Generate a web page describing each module's feature",
execute = Feature.Generate
}

View File

@ -0,0 +1,89 @@
return {
Title = "Module audio",
LibName = "NazaraAudio",
Description = "Module permettant de charger et jouer des sons, ainsi que d'accéder au microphone",
RequiredPortability = Feature.Windows + Feature.POSIX,
Features =
{
{
Title = "Gestion des émetteurs de sons (SoundEmitter)",
Description = "Classe de base dont héritent les sources sonores (Music, Sound)",
Features =
{
"Positionnement 3D (spatialisation) si désiré",
"Configuration de l'atténuation",
"Prise en charge de l'effet Doppler (vitesse du son)",
"Altération du ton (pitch)"
}
},
{
Title = "Gestion des tampons sonores (SoundBuffer)",
Description = "Tampon (buffer) stockant les échantillons (samples) décompressés, chargés à partir de fichiers sonores.",
Features =
{
{
Title = "Mixage mono",
Description = "Permet de mixer les différents canaux en un seul (mono), permettant la spatialisation.",
Note = "Le mixage mono n'est actuellement possible qu'au chargement du tampon depuis un fichier",
Progress = 90
}
}
},
{
Title = "Gestion des flux sonores (SoundStream)",
Description = "Interface permettant de définir un flux sonore de source indéfinie (fichier, réseau, etc.)"
},
{
Title = "Sons (Sound)",
Description = "Classe permettant de jouer un tampon sonore",
Features =
{
"Bouclage",
"Mise en pause",
"Récupération/positionnement de l'indice de lecture (offset)"
}
},
{
Title = "Sons streamés (Music)",
Description = "Classe permettant de jouer un son depuis un flux quelconque (SoundStream)",
Features =
{
"Streaming depuis un fichier sonore (+ mixage mono si demandé)",
"Bouclage",
"Mise en pause",
{Title = "Mixage mono", Note = "Le mixage mono devrait être possible au niveau du son lui-même plutôt qu'au niveau du loader", Progress = 0},
{Title = "Récupération/positionnement de l'indice de lecture (offset)", Progress = 0}
}
},
{
Title = "Configuration globale (Audio)",
Description = "Classe permettant de régler les différents paramètres généraux de l'environnement sonore",
Features =
{
"Positionnement/Orientation du listener",
"Réglage du volume général",
"Réglage de la vitesse du son/facteur Doppler"
}
},
{
Title = "Microphone",
Description = "Classe permettant l'accès aux microphones connectés à l'ordinateur",
Progress = 0
},
{
Title = "Environnement (EFX)",
Description = "Prise en charge de l'environnement",
Progress = 0
},
{
Title = "Formats supportés (chargement/streaming)",
Description = "Liste des formats de fichiers supportés par le loader inclus par le module (libsndfile)",
Note = "Le populaire format MP3 n'est pas supporté pour des raisons de royalties (mais la flexibilité du moteur vous permet de rajouter votre propre loader MP3)",
Features =
{
"aiff", "au", "avr", "caf", "flac", "htk", "ircam", "mat4", "mat5", "mpc2k", "nist","ogg", "pvf", "raw", "rf64", "sd2", "sds", "svx", "voc", "w64", "wav", "wve"
}
}
}
}

View File

@ -0,0 +1,204 @@
return {
Title = "Noyau",
LibName = "NazaraCore",
Description = "Noyau du moteur, possède les fonctionnalités utilisées partout ailleurs dans le moteur.",
RequiredPortability = Feature.Windows + Feature.POSIX,
Features =
{
{
Title = "Classes utilitaires de base",
Description = "Classes assurant certaines fonctionnalités de base destinées à aider le programmeur.",
Features =
{
{
Title = "Chaînes de caractère unicode (String)",
Description = "Classe supplantant std::string, rajoutant le support de l'UTF-8 et quelques opérations utiles (rechercher/remplacer, correspondance par motif, ..)."
},
{
Title = "Exécution de code lors de la destruction (CallOnExit)",
Description = "Permet l'appel d'une fonction/lambda à la destruction de cet objet, en accordance avec le RAII/RRID."
},
{
Title = "Gestion de l'initialisation/libération statique de classes, en accordance avec le RAII/RRID",
Description = "Permet d'initialiser et de libérer automatiquement des classes possédant des fonctions membres statiques Initialize/Uninitialize, selon un ordre de dépendance, comme par exemple les classes des modules du moteur lui-même."
},
{
Title = "Gestion des couleurs (Color)",
Description = "Classe permettant de stocker et effectuer des opérations sur des couleurs (conversion, mélange, etc.)."
},
{
Title = "Gestion de primitives, au sens géométrique (Primitive, PrimitiveList)",
Description = "Structures définissant certaines primitives géométriques (boite, cône, plan, sphère), utiles pour la génération de meshs (de rendu ou physiques)."
},
{
Title = "OffsetOf",
Description = "Fonction permettant de récupérer à la compilation l'adresse locale (décalage d'octets) d'un membre de n'importe quelle structure/classe."
},
{
Title = "Pointeurs à écart (stride) indépendant (SparsePtr)",
Description = "Classe se comportant comme un pointeur, à l'exception de l'écart entre deux éléments (opérations d'accès, d'addition et de soustraction) qui est indépendant du type pointé."
},
{
Title = "Stockage et gestion de champs de bits dynamiques (Bitset)",
Description = "Classe permettant le stockage et la manipulation optimisée d'un nombre élevé et dynamique de bits (=booléens, opérations de comptage, recherche de bits activés, opérations entre champs de bits, etc.)",
Note = "Il manque des opérateurs de comparaison et une spécialisation de la fonction de hachage",
Progress = 90
}
}
},
{
Title = "Gestion de fichiers et dossiers (File/Directory)",
Description = "Classes supportant les chemins unicodes et les tailles 64 bits, ainsi que quelques opérations sur les chemins (normalisation, transformation d'un chemin relatif en chemin absolu).",
Portability = Feature.Windows + Feature.POSIX
},
{
Title = "Gestion de l'endianness",
Description = "Boutisme, récupération à la compilation ou à l'exécution, possibilité de lire des fichiers en corrigeant le boutisme des objets lors de la lecture."
},
{
Title = "Gestion de bibliothèques dynamiques (DynLib)",
Description = "Classe permettant de charger à l'exécution des bibliothèques dynamiques (selon la plateforme: .dll/.so/.dynlib) et d'en extraire des fonctions.",
Portability = Feature.Windows + Feature.POSIX
},
{
Title = "Fonctions de hachage",
Description = "Possibilité de hacher (calculer une somme de contrôle) de n'importe quelles données, chaîne de caractère ou fichier.",
Features =
{
{Title = "CRC16", Progress = 0},
"CRC32",
"Fletcher16",
{Title = "Fletcher32", Progress = 0},
"MD5",
"SHA-1",
"SHA-224",
"SHA-256",
"SHA-384",
"SHA-512",
"Whirlpool"
}
},
{
Title = "Gestion de la mémoire",
Description = "Set de fonctionnalités permettant d'aider le programmeur à gérer la mémoire de son programme.",
Features =
{
{
Title = "MemoryManager",
Description = "Classe permettant de suivre les allocations de mémoire et éventuels leaks, peut suivre automatiquement chaque allocation du programme."
},
{
Title = "MemoryPool",
Description = "Classe permettant d'allouer/libérer des blocs de mémoire de taille prédéfinie à coût constant."
}
}
},
{
Title = "Gestion de l'exécution concurrentielle",
Description = "Set de fonctionnalités liées à l'exécution et la synchronisation entre processus légers (threads) sans dépendance sur la bibliothèque standard.",
Features =
{
{
Title = "Thread",
Description = "Classe permettant d'appeler une fonction (avec passage d'arguments) dans un thread, supporte une interface similaire à std::thread.",
Note = "Il n'est pas encore possible de récupérer le Thread::Id courant",
Progress = 95,
Portability = Feature.Windows + Feature.POSIX
},
{
Title = "Mutex",
Description = "Primitive de synchronisation binaire (exclusion mutuelle).",
Portability = Feature.Windows + Feature.POSIX
},
{
Title = "Semaphore",
Description = "Primitive de synchronisation à N concurrents simultanés.",
Portability = Feature.Windows + Feature.POSIX
},
{
Title = "ConditionVariable",
Description = "Primitive de synchronisation à signaux.",
Portability = Feature.Windows + Feature.POSIX
},
{
Title = "LockGuard",
Description = "Classe utilitaire permettant de verrouiller/déverrouiller une mutex en accordance avec le RAII/RRID."
},
{
Title = "TaskScheduler",
Description = "Classe permettant de répartir X tâches sur Y workers de façon efficace.",
Portability = Feature.Windows
}
}
},
{
Title = "Gestion du temps",
Description = "Classes/fonctions permettant de gérer le temps dans un programme.",
Features =
{
{
Title = "Récupération du temps en millisecondes ou en microsecondes",
Description = "Permet de récupérer le nombre de millisecondes ou de microsecondes (si supporté par le système) écoulées depuis un référentiel constant (référentiel indéterminé).",
Portability = Feature.Windows + Feature.POSIX
},
{
Title = "Clock",
Description = "Classe chronomètre permettant de mesurer le temps écoulé depuis un évènement précis, supporte la mise en pause."
}
}
},
{
Title = "Gestion de compteurs de référence",
Description = "Set de classes permettant de gérer des pointeurs intelligents partagés intrusifs.",
},
{
Title = "Gestion de liste de paramètres",
Description = "Classe gérant une liste de paramètres nommées à type variable.",
},
{
Title = "Gestion de ressources (chargement/gestion)",
Description = "Set de classes s'occupant du chargement et de la gestion de certaines classes spéciales, appartenant au groupe des ressources (ex: chargée depuis un fichier).",
Features =
{
{
Title = "ResourceLibrary",
Description = "Classe template chargée du stockage de ressources de façon nommée."
},
{
Title = "ResourceLoader",
Description = "Classe template chargée de stocker et gérer des loaders (fonctions s'occupant de transformer un flux de données en ressource)."
},
{
Title = "ResourceManager",
Description = "Classe template chargée de charger et mettre en cache des ressources depuis un chemin de fichier."
}
}
},
{
Title = "Gestion des plugins",
Description = "Capacité d'extension du moteur à l'aide de bibliothèques dynamiques conçues dans cette optique.",
Note = "Nécessite une révision, permettant aux plugins de se signaler (nom, version)",
Progress = 80
},
{
Title = "Gestion de l'empaquetage bidimensionnel",
Description = "Algorithmes permettant de placer des rectangles 2D arbitraires dans un espace prédéfini de façon à minimiser la perte d'espace.",
Note = "Algorithme Guillotine terminé, algorithme Skyline manquant",
Progress = 60
},
{
Title = "Gestion de l'Unicode",
Description = "Récupération d'informations sur les caractères Unicode (si les données Unicode sont incorporées au programme).",
Note = "Il manque l'intégration des UnicodeData dans le moteur",
Progress = 20
},
{
Title = "Récupération d'informations sur le hardware",
Description = "Classe permettant, si la plateforme le supporte, de récupérer des informations utiles sur le matériel: nom et fabricant du processeur, nombre de coeurs, support d'un set d'extension (exemple: SSE), quantité de mémoire vive, exécution de l'instruction CPUID.",
Note = "Il manque de quoi récupérer la quantité de mémoire vive",
Progress = 90,
Portability = Feature.Windows + Feature.POSIX
}
}
}

View File

@ -0,0 +1,75 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="stylesheet" href="style.css" />
<title>Avancement de Nazara</title>
</head>
<body>
<p class="centre">
<img src="https://github.com/DigitalPulseSoftware/NazaraEngine/raw/master/Logo.png" alt="Nazara Engine" />
<br>
<br>
Retrouvez le moteur sur GitHub !
<br>
<a href="https://github.com/DigitalPulseSoftware/NazaraEngine">Dépôt Github</a><br><br>
Ou venez vous renseigner sur les topics dédiés à Nazara présents sur plusieurs site webs:
<br>
<a href="http://openclassrooms.com/forum/sujet/moteur-de-jeu-nazara-engine-69732">OpenClassrooms</a> ou <a href="http://pdp.microjoe.org/forums/sujet/354/projet-nazara-engine-moteur-de-jeu">Progdupeupl</a> ou <a href="http://zestedesavoir.com/forums/sujet/1039/nazara-engine">ZesteDeSavoir</a>
<br>
<br>
... ou pourquoi ne pas venir faire un tour sur <a href="http://forum.digitalpulsesoftware.com">le forum dédié au moteur</a> ?
</p>
<div class="centre">
<h1>Fonctionnalités de Nazara</h1>
<br>
Dernière mise à jour:
<span class="lastupdate">
%DATE%
</span>
<br>
<br>
<h2>Important:</h2><br>
Afin de faciliter la mise à jour, la page que vous voyez ici a été généré automatiquement par un script Lua, ce qui m'oblige néanmoins à encoder les fonctionnalités de chaque module dans un premier temps.<br>
C'est un travail assez long (pour vous donner une idée, les données du noyau représentent un fichier de 200 lignes), et il n'est pas encore complet, c'est pourquoi des modules manquent sur cette page.<br>
Gardez donc à l'esprit que le moteur possède plus de fonctionnalités que ce qui est décrit actuellement sur cette page.<br>
<br>
Oh et bien sûr je ne suis pas concepteur de site web, c'est pourquoi cette page est moche (j'ai <u>essayé</u> de minimiser les dégats).<br>
Si vous sentez en vous l'irrésistible envie d'améliorer cette page, sachez que votre aide sera grandement appréciée (vous pouvez me contacter via le lien de votre choix plus haut).
<br>
<br>
Le pourcentage indiqué est calculé automatiquement en fonction des <u>fonctionnalités</u>,<br>cela signifie qu'une fonctionnalité présente sera comptée à 100% à partir du moment où son implémentation de base est considérée fonctionnelle,<br><u>cela n'est donc pas une assurance qu'aucun bug n'existe concernant cette fonctionnalité</u> (cependant cela signifie que la fonctionnalité est utilisable).<br>
Et bien entendu, un module ou une fonctionnalité ayant atteint les 100% peut toujours évoluer par la suite.
<br>
<br>
<table>
<caption>Sommaire</caption>
<thead>
<tr>
<th>Module</th>
<th>Avancement</th>
</tr>
</thead>
<tbody>
%MODULELIST%
</tbody>
</table>
</div>
%MODULEDESCRIPTION%
<hr />
<div class="centre">
<table>
<caption>Sommaire</caption>
<thead>
<tr>
<th>Module</th>
<th>Pourcentage</th>
</tr>
</thead>
<tbody>
%MODULELIST%
</tbody>
</table>
</div>
</body>
</html>

View File

@ -0,0 +1,108 @@
/* Je ne suis pas développeur HTML/CSS, je dois y toucher une fois l'an, désolé pour les quelques atrocités que vous pourrez trouver ici */
body
{
background-color: black;
color: white;
}
a
{
color: #007ACC;
}
a:hover
{
color: lightblue;
}
h1
{
display: inline;
}
h2
{
display: inline;
text-decoration: underline;
}
h4
{
text-decoration: underline;
}
ol
{
list-style-type: none;
}
table
{
border-collapse: collapse;
text-align: center;
display: inline-block;
border: white groove;
border-radius: 10px;
box-shadow: 0px 0px 10px lightblue;
}
th
{
text-shadow: 2px 2px 4px black;
}
tr
{
border: 1px solid white;
}
tbody tr:hover
{
text-shadow: 0px 0px 4px white;
}
.centre
{
text-align: center;
}
.description
{
margin-left: 20px;
}
.lastupdate
{
font-size: x-large;
font-weight: bold;
color: yellow;
}
.module
{
}
.modulename
{
font-size: x-large;
font-weight: bold;
text-shadow: 2px 2px 10px #007ACC;
}
.note
{
margin-left: 20px;
color: #007ACC;
}
.notedesc
{
color: rgb(200, 200, 255);
}
.portability
{
margin-left: 20px;
color: red;
}

View File

@ -8,6 +8,7 @@
template<typename T> template<typename T>
void NzMixToMono(T* input, T* output, unsigned int channelCount, unsigned int frameCount) void NzMixToMono(T* input, T* output, unsigned int channelCount, unsigned int frameCount)
{ {
///DOC: Le buffer d'entrée peut être le même que le buffer de sortie
// Pour éviter l'overflow, on utilise comme accumulateur un type assez grand, (u)int 64 bits pour les entiers, double pour les flottants // Pour éviter l'overflow, on utilise comme accumulateur un type assez grand, (u)int 64 bits pour les entiers, double pour les flottants
typedef typename std::conditional<std::is_unsigned<T>::value, nzUInt64, nzInt64>::type BiggestInt; typedef typename std::conditional<std::is_unsigned<T>::value, nzUInt64, nzInt64>::type BiggestInt;
typedef typename std::conditional<std::is_integral<T>::value, BiggestInt, double>::type Biggest; typedef typename std::conditional<std::is_integral<T>::value, BiggestInt, double>::type Biggest;

View File

@ -10,7 +10,7 @@
/// Ce fichier sert à vérifier la valeur des constantes du fichier Config.hpp /// Ce fichier sert à vérifier la valeur des constantes du fichier Config.hpp
#include <type_traits> #include <type_traits>
#define CheckTypeAndVal(name, type, op, val, err) static_assert(std::is_ ##type <decltype(name)>::value && name op val, #type err) #define NazaraCheckTypeAndVal(name, type, op, val, err) static_assert(std::is_ ##type <decltype(name)>::value && name op val, #type err)
// On force la valeur de MANAGE_MEMORY en mode debug // On force la valeur de MANAGE_MEMORY en mode debug
#if defined(NAZARA_DEBUG) && !NAZARA_AUDIO_MANAGE_MEMORY #if defined(NAZARA_DEBUG) && !NAZARA_AUDIO_MANAGE_MEMORY
@ -18,6 +18,8 @@
#define NAZARA_AUDIO_MANAGE_MEMORY 1 #define NAZARA_AUDIO_MANAGE_MEMORY 1
#endif #endif
CheckTypeAndVal(NAZARA_AUDIO_STREAMED_BUFFER_COUNT, integral, >, 0, " shall be a strictly positive integer"); NazaraCheckTypeAndVal(NAZARA_AUDIO_STREAMED_BUFFER_COUNT, integral, >, 0, " shall be a strictly positive integer");
#undef NazaraCheckTypeAndVal
#endif // NAZARA_CONFIG_CHECK_AUDIO_HPP #endif // NAZARA_CONFIG_CHECK_AUDIO_HPP

View File

@ -4,13 +4,16 @@
#pragma once #pragma once
#ifndef NAZARA_TUPLE_HPP #ifndef NAZARA_ALGORITHM_CORE_HPP
#define NAZARA_TUPLE_HPP #define NAZARA_ALGORITHM_CORE_HPP
#include <Nazara/Prerequesites.hpp>
#include <functional>
#include <tuple> #include <tuple>
template<typename T> void NzHashCombine(std::size_t& seed, const T& v);
template<typename F, typename... ArgsT> void NzUnpackTuple(F func, const std::tuple<ArgsT...>& t); template<typename F, typename... ArgsT> void NzUnpackTuple(F func, const std::tuple<ArgsT...>& t);
#include <Nazara/Core/Tuple.inl> #include <Nazara/Core/Algorithm.inl>
#endif // NAZARA_TUPLE_HPP #endif // NAZARA_ALGORITHM_CORE_HPP

View File

@ -8,6 +8,8 @@
#include <Nazara/Core/Debug.hpp> #include <Nazara/Core/Debug.hpp>
///TODO: Améliorer l'implémentation de UnpackTuple
template<unsigned int N> template<unsigned int N>
struct NzImplTupleUnpack struct NzImplTupleUnpack
{ {
@ -28,6 +30,23 @@ struct NzImplTupleUnpack<0>
} }
}; };
// Algorithme venant de CityHash par Google
// http://stackoverflow.com/questions/8513911/how-to-create-a-good-hash-combine-with-64-bit-output-inspired-by-boosthash-co
template<typename T>
void NzHashCombine(std::size_t& seed, const T& v)
{
const nzUInt64 kMul = 0x9ddfea08eb382d69ULL;
std::hash<T> hasher;
nzUInt64 a = (hasher(v) ^ seed) * kMul;
a ^= (a >> 47);
nzUInt64 b = (seed ^ a) * kMul;
b ^= (b >> 47);
seed = static_cast<std::size_t>(b * kMul);
}
template<typename F, typename... ArgsT> template<typename F, typename... ArgsT>
void NzUnpackTuple(F func, const std::tuple<ArgsT...>& t) void NzUnpackTuple(F func, const std::tuple<ArgsT...>& t)
{ {

View File

@ -148,7 +148,7 @@ inline NzColor NzColor::FromHSV(float hue, float saturation, float value)
if (NzNumberEquals(h, 6.f)) if (NzNumberEquals(h, 6.f))
h = 0; // hue must be < 1 h = 0; // hue must be < 1
int i = h; int i = static_cast<unsigned int>(h);
float v1 = value * (1.f - s); float v1 = value * (1.f - s);
float v2 = value * (1.f - s * (h - i)); float v2 = value * (1.f - s * (h - i));
float v3 = value * (1.f - s * (1.f - (h - i))); float v3 = value * (1.f - s * (1.f - (h - i)));

View File

@ -10,7 +10,7 @@
/// Ce fichier sert à vérifier la valeur des constantes du fichier Config.hpp /// Ce fichier sert à vérifier la valeur des constantes du fichier Config.hpp
#include <type_traits> #include <type_traits>
#define CheckTypeAndVal(name, type, op, val, err) static_assert(std::is_ ##type <decltype(name)>::value && name op val, #type err) #define NazaraCheckTypeAndVal(name, type, op, val, err) static_assert(std::is_ ##type <decltype(name)>::value && name op val, #type err)
// On force la valeur de MANAGE_MEMORY en mode debug // On force la valeur de MANAGE_MEMORY en mode debug
#if defined(NAZARA_DEBUG) && !NAZARA_CORE_MANAGE_MEMORY #if defined(NAZARA_DEBUG) && !NAZARA_CORE_MANAGE_MEMORY
@ -18,8 +18,10 @@
#define NAZARA_CORE_MANAGE_MEMORY 1 #define NAZARA_CORE_MANAGE_MEMORY 1
#endif #endif
CheckTypeAndVal(NAZARA_CORE_DECIMAL_DIGITS, integral, >, 0, " shall be a strictly positive integer"); NazaraCheckTypeAndVal(NAZARA_CORE_DECIMAL_DIGITS, integral, >, 0, " shall be a strictly positive integer");
CheckTypeAndVal(NAZARA_CORE_FILE_BUFFERSIZE, integral, >, 0, " shall be a strictly positive integer"); NazaraCheckTypeAndVal(NAZARA_CORE_FILE_BUFFERSIZE, integral, >, 0, " shall be a strictly positive integer");
CheckTypeAndVal(NAZARA_CORE_WINDOWS_CS_SPINLOCKS, integral, >=, 0, " shall be a positive integer"); NazaraCheckTypeAndVal(NAZARA_CORE_WINDOWS_CS_SPINLOCKS, integral, >=, 0, " shall be a positive integer");
#undef NazaraCheckTypeAndVal
#endif // NAZARA_CONFIG_CHECK_CORE_HPP #endif // NAZARA_CONFIG_CHECK_CORE_HPP

View File

@ -15,7 +15,8 @@
#if defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || (defined(__MIPS__) && defined(__MISPEB__)) || \ #if defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || (defined(__MIPS__) && defined(__MISPEB__)) || \
defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC) || defined(__sparc__) || defined(__hppa__) defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC) || defined(__sparc__) || defined(__hppa__)
#define NAZARA_BIG_ENDIAN #define NAZARA_BIG_ENDIAN
#elif defined(__i386__) || defined(__i386) || defined(__X86__) || defined (__x86_64) #elif defined(__i386__) || defined(__i386) || defined(__X86__) || defined (__x86_64) || defined(_M_I86) || \
defined(_M_IX86) || defined(_M_X64)
#define NAZARA_LITTLE_ENDIAN #define NAZARA_LITTLE_ENDIAN
#else #else
#error Failed to identify endianness, you must define either NAZARA_BIG_ENDIAN or NAZARA_LITTLE_ENDIAN #error Failed to identify endianness, you must define either NAZARA_BIG_ENDIAN or NAZARA_LITTLE_ENDIAN

View File

@ -7,7 +7,7 @@
#ifndef NAZARA_FUNCTOR_HPP #ifndef NAZARA_FUNCTOR_HPP
#define NAZARA_FUNCTOR_HPP #define NAZARA_FUNCTOR_HPP
#include <Nazara/Core/Tuple.hpp> #include <Nazara/Core/Algorithm.hpp>
// Inspiré du code de la SFML par Laurent Gomila // Inspiré du code de la SFML par Laurent Gomila

View File

@ -14,6 +14,8 @@
class NAZARA_API NzHardwareInfo class NAZARA_API NzHardwareInfo
{ {
public: public:
static void Cpuid(nzUInt32 functionId, nzUInt32 subFunctionId, nzUInt32 result[4]);
static NzString GetProcessorBrandString(); static NzString GetProcessorBrandString();
static unsigned int GetProcessorCount(); static unsigned int GetProcessorCount();
static nzProcessorVendor GetProcessorVendor(); static nzProcessorVendor GetProcessorVendor();
@ -23,6 +25,7 @@ class NAZARA_API NzHardwareInfo
static bool Initialize(); static bool Initialize();
static bool IsCpuidSupported();
static bool IsInitialized(); static bool IsInitialized();
static void Uninitialize(); static void Uninitialize();

View File

@ -13,6 +13,8 @@
#include <set> #include <set>
#include <unordered_map> #include <unordered_map>
///TODO: Révision
class NzDynLib; class NzDynLib;
class NAZARA_API NzPluginManager class NAZARA_API NzPluginManager

View File

@ -50,8 +50,6 @@ class NAZARA_API NzRefCounted
private: private:
using ObjectListenerMap = std::unordered_map<NzObjectListener*, std::pair<int, unsigned int>>; using ObjectListenerMap = std::unordered_map<NzObjectListener*, std::pair<int, unsigned int>>;
void RemoveObjectListenerIterator(ObjectListenerMap::iterator iterator) const;
NazaraMutexAttrib(m_mutex, mutable) NazaraMutexAttrib(m_mutex, mutable)
mutable ObjectListenerMap m_objectListeners; mutable ObjectListenerMap m_objectListeners;

View File

@ -87,10 +87,10 @@ class NAZARA_API NzString : public NzHashable
const char* GetConstBuffer() const; const char* GetConstBuffer() const;
unsigned int GetLength() const; unsigned int GetLength() const;
unsigned int GetSize() const; unsigned int GetSize() const;
char* GetUtf8Buffer(unsigned int* size = nullptr) const; std::string GetUtf8String() const;
char16_t* GetUtf16Buffer(unsigned int* size = nullptr) const; std::u16string GetUtf16String() const;
char32_t* GetUtf32Buffer(unsigned int* size = nullptr) const; std::u32string GetUtf32String() const;
wchar_t* GetWideBuffer(unsigned int* size = nullptr) const; std::wstring GetWideString() const;
NzString GetWord(unsigned int index, nzUInt32 flags = None) const; NzString GetWord(unsigned int index, nzUInt32 flags = None) const;
unsigned int GetWordPosition(unsigned int index, nzUInt32 flags = None) const; unsigned int GetWordPosition(unsigned int index, nzUInt32 flags = None) const;

View File

@ -10,7 +10,7 @@
#include <Nazara/Prerequesites.hpp> #include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/Functor.hpp> #include <Nazara/Core/Functor.hpp>
#include <Nazara/Core/NonCopyable.hpp> #include <Nazara/Core/NonCopyable.hpp>
#include <ostream> #include <iosfwd>
class NzThreadImpl; class NzThreadImpl;

View File

@ -10,7 +10,7 @@
/// Ce fichier sert à vérifier la valeur des constantes du fichier Config.hpp /// Ce fichier sert à vérifier la valeur des constantes du fichier Config.hpp
#include <type_traits> #include <type_traits>
#define CheckTypeAndVal(name, type, op, val, err) static_assert(std::is_ ##type <decltype(name)>::value && name op val, #type err) #define NazaraCheckTypeAndVal(name, type, op, val, err) static_assert(std::is_ ##type <decltype(name)>::value && name op val, #type err)
// On force la valeur de MANAGE_MEMORY en mode debug // On force la valeur de MANAGE_MEMORY en mode debug
#if defined(NAZARA_DEBUG) && !NAZARA_GRAPHICS_MANAGE_MEMORY #if defined(NAZARA_DEBUG) && !NAZARA_GRAPHICS_MANAGE_MEMORY
@ -18,7 +18,9 @@
#define NAZARA_GRAPHICS_MANAGE_MEMORY 1 #define NAZARA_GRAPHICS_MANAGE_MEMORY 1
#endif #endif
CheckTypeAndVal(NAZARA_GRAPHICS_INSTANCING_MIN_INSTANCES_COUNT, integral, >, 0, " shall be a strictly positive integer"); NazaraCheckTypeAndVal(NAZARA_GRAPHICS_INSTANCING_MIN_INSTANCES_COUNT, integral, >, 0, " shall be a strictly positive integer");
CheckTypeAndVal(NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS, integral, >, 0, " shall be a strictly positive integer"); NazaraCheckTypeAndVal(NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS, integral, >, 0, " shall be a strictly positive integer");
#undef NazaraCheckTypeAndVal
#endif // NAZARA_CONFIG_CHECK_GRAPHICS_HPP #endif // NAZARA_CONFIG_CHECK_GRAPHICS_HPP

View File

@ -109,31 +109,31 @@ class NAZARA_API NzMaterial : public NzRefCounted, public NzResource
void Reset(); void Reset();
bool SetAlphaMap(const NzString& name); bool SetAlphaMap(const NzString& textureName);
void SetAlphaMap(NzTexture* map); void SetAlphaMap(NzTextureRef alphaMap);
void SetAlphaThreshold(float alphaThreshold); void SetAlphaThreshold(float alphaThreshold);
void SetAmbientColor(const NzColor& ambient); void SetAmbientColor(const NzColor& ambient);
void SetDepthFunc(nzRendererComparison depthFunc); void SetDepthFunc(nzRendererComparison depthFunc);
void SetDiffuseColor(const NzColor& diffuse); void SetDiffuseColor(const NzColor& diffuse);
bool SetDiffuseMap(const NzString& name); bool SetDiffuseMap(const NzString& textureName);
void SetDiffuseMap(NzTexture* map); void SetDiffuseMap(NzTextureRef diffuseMap);
void SetDiffuseSampler(const NzTextureSampler& sampler); void SetDiffuseSampler(const NzTextureSampler& sampler);
void SetDstBlend(nzBlendFunc func); void SetDstBlend(nzBlendFunc func);
bool SetEmissiveMap(const NzString& name); bool SetEmissiveMap(const NzString& textureName);
void SetEmissiveMap(NzTexture* map); void SetEmissiveMap(NzTextureRef textureName);
void SetFaceCulling(nzFaceSide faceSide); void SetFaceCulling(nzFaceSide faceSide);
void SetFaceFilling(nzFaceFilling filling); void SetFaceFilling(nzFaceFilling filling);
bool SetHeightMap(const NzString& name); bool SetHeightMap(const NzString& textureName);
void SetHeightMap(NzTexture* map); void SetHeightMap(NzTextureRef textureName);
bool SetNormalMap(const NzString& name); bool SetNormalMap(const NzString& textureName);
void SetNormalMap(NzTexture* map); void SetNormalMap(NzTextureRef textureName);
void SetRenderStates(const NzRenderStates& states); void SetRenderStates(const NzRenderStates& states);
void SetShader(const NzUberShader* uberShader); void SetShader(NzUberShaderConstRef uberShader);
bool SetShader(const NzString& uberShaderName); bool SetShader(const NzString& uberShaderName);
void SetShininess(float shininess); void SetShininess(float shininess);
void SetSpecularColor(const NzColor& specular); void SetSpecularColor(const NzColor& specular);
bool SetSpecularMap(const NzString& name); bool SetSpecularMap(const NzString& textureName);
void SetSpecularMap(NzTexture* map); void SetSpecularMap(NzTextureRef specularMap);
void SetSpecularSampler(const NzTextureSampler& sampler); void SetSpecularSampler(const NzTextureSampler& sampler);
void SetSrcBlend(nzBlendFunc func); void SetSrcBlend(nzBlendFunc func);

View File

@ -40,14 +40,10 @@ class NAZARA_API NzModel : public NzResource, public NzSceneNode
virtual ~NzModel(); virtual ~NzModel();
void AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const override; void AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const override;
void AdvanceAnimation(float elapsedTime);
NzModel* Clone() const; NzModel* Clone() const;
NzModel* Create() const; NzModel* Create() const;
void EnableAnimation(bool animation);
NzAnimation* GetAnimation() const;
NzMaterial* GetMaterial(const NzString& subMeshName) const; NzMaterial* GetMaterial(const NzString& subMeshName) const;
NzMaterial* GetMaterial(unsigned int matIndex) const; NzMaterial* GetMaterial(unsigned int matIndex) const;
NzMaterial* GetMaterial(unsigned int skinIndex, const NzString& subMeshName) const; NzMaterial* GetMaterial(unsigned int skinIndex, const NzString& subMeshName) const;
@ -57,12 +53,7 @@ class NAZARA_API NzModel : public NzResource, public NzSceneNode
unsigned int GetSkinCount() const; unsigned int GetSkinCount() const;
NzMesh* GetMesh() const; NzMesh* GetMesh() const;
nzSceneNodeType GetSceneNodeType() const override; nzSceneNodeType GetSceneNodeType() const override;
NzSkeleton* GetSkeleton();
const NzSkeleton* GetSkeleton() const;
bool HasAnimation() const;
bool IsAnimationEnabled() const;
virtual bool IsAnimated() const; virtual bool IsAnimated() const;
bool IsDrawable() const; bool IsDrawable() const;

View File

@ -16,6 +16,7 @@
#include <Nazara/Graphics/ParticleRenderer.hpp> #include <Nazara/Graphics/ParticleRenderer.hpp>
#include <Nazara/Graphics/SceneNode.hpp> #include <Nazara/Graphics/SceneNode.hpp>
#include <Nazara/Math/BoundingVolume.hpp> #include <Nazara/Math/BoundingVolume.hpp>
#include <functional>
#include <memory> #include <memory>
#include <set> #include <set>
#include <vector> #include <vector>

View File

@ -23,7 +23,7 @@ class NAZARA_API NzSceneNode : public NzNode
public: public:
NzSceneNode(); NzSceneNode();
NzSceneNode(const NzSceneNode& sceneNode); NzSceneNode(const NzSceneNode& sceneNode);
NzSceneNode(NzSceneNode& sceneNode) = delete; NzSceneNode(NzSceneNode&& sceneNode) = delete;
virtual ~NzSceneNode(); virtual ~NzSceneNode();
virtual void AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const = 0; virtual void AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const = 0;

View File

@ -35,15 +35,20 @@ class NAZARA_API NzView : public NzAbstractViewer, public NzNode, NzRenderTarget
NzVector3f GetGlobalForward() const; NzVector3f GetGlobalForward() const;
NzVector3f GetGlobalRight() const; NzVector3f GetGlobalRight() const;
NzVector3f GetGlobalUp() const; NzVector3f GetGlobalUp() const;
const NzMatrix4f& GetInvViewProjMatrix() const;
const NzMatrix4f& GetProjectionMatrix() const; const NzMatrix4f& GetProjectionMatrix() const;
const NzVector2f& GetSize() const; const NzVector2f& GetSize() const;
const NzRenderTarget* GetTarget() const; const NzRenderTarget* GetTarget() const;
const NzRectf& GetTargetRegion() const; const NzRectf& GetTargetRegion() const;
const NzMatrix4f& GetViewMatrix() const; const NzMatrix4f& GetViewMatrix() const;
const NzMatrix4f& GetViewProjMatrix() const;
const NzRecti& GetViewport() const; const NzRecti& GetViewport() const;
float GetZFar() const; float GetZFar() const;
float GetZNear() const; float GetZNear() const;
NzVector2i MapWorldToPixel(const NzVector2f& coords);
NzVector2f MapPixelToWorld(const NzVector2i& pixel);
void SetSize(const NzVector2f& size); void SetSize(const NzVector2f& size);
void SetSize(float width, float height); void SetSize(float width, float height);
void SetTarget(const NzRenderTarget* renderTarget); void SetTarget(const NzRenderTarget* renderTarget);
@ -61,20 +66,26 @@ class NAZARA_API NzView : public NzAbstractViewer, public NzNode, NzRenderTarget
bool OnRenderTargetSizeChange(const NzRenderTarget* renderTarget, void* userdata) override; bool OnRenderTargetSizeChange(const NzRenderTarget* renderTarget, void* userdata) override;
void UpdateFrustum() const; void UpdateFrustum() const;
void UpdateInvViewProjMatrix() const;
void UpdateProjectionMatrix() const; void UpdateProjectionMatrix() const;
void UpdateViewMatrix() const; void UpdateViewMatrix() const;
void UpdateViewProjMatrix() const;
void UpdateViewport() const; void UpdateViewport() const;
mutable NzFrustumf m_frustum; mutable NzFrustumf m_frustum;
mutable NzMatrix4f m_invViewProjMatrix;
mutable NzMatrix4f m_projectionMatrix; mutable NzMatrix4f m_projectionMatrix;
mutable NzMatrix4f m_viewMatrix; mutable NzMatrix4f m_viewMatrix;
mutable NzMatrix4f m_viewProjMatrix;
NzRectf m_targetRegion; NzRectf m_targetRegion;
mutable NzRecti m_viewport; mutable NzRecti m_viewport;
NzVector2f m_size; NzVector2f m_size;
const NzRenderTarget* m_target; const NzRenderTarget* m_target;
mutable bool m_frustumUpdated; mutable bool m_frustumUpdated;
mutable bool m_invViewProjMatrixUpdated;
mutable bool m_projectionMatrixUpdated; mutable bool m_projectionMatrixUpdated;
mutable bool m_viewMatrixUpdated; mutable bool m_viewMatrixUpdated;
mutable bool m_viewProjMatrixUpdated;
mutable bool m_viewportUpdated; mutable bool m_viewportUpdated;
float m_zFar; float m_zFar;
float m_zNear; float m_zNear;

View File

@ -38,8 +38,8 @@ class NAZARA_API NzLuaInstance : NzNonCopyable
void CheckAny(int index) const; void CheckAny(int index) const;
bool CheckBoolean(int index) const; bool CheckBoolean(int index) const;
bool CheckBoolean(int index, bool defValue) const; bool CheckBoolean(int index, bool defValue) const;
int CheckInteger(int index) const; long long CheckInteger(int index) const;
int CheckInteger(int index, int defValue) const; long long CheckInteger(int index, long long defValue) const;
double CheckNumber(int index) const; double CheckNumber(int index) const;
double CheckNumber(int index, double defValue) const; double CheckNumber(int index, double defValue) const;
void CheckStack(int space, const char* error = nullptr) const; void CheckStack(int space, const char* error = nullptr) const;
@ -47,8 +47,6 @@ class NAZARA_API NzLuaInstance : NzNonCopyable
const char* CheckString(int index, std::size_t* length = nullptr) const; const char* CheckString(int index, std::size_t* length = nullptr) const;
const char* CheckString(int index, const char* defValue, std::size_t* length = nullptr) const; const char* CheckString(int index, const char* defValue, std::size_t* length = nullptr) const;
void CheckType(int index, nzLuaType type) const; void CheckType(int index, nzLuaType type) const;
unsigned int CheckUnsigned(int index) const;
unsigned int CheckUnsigned(int index, unsigned int defValue) const;
void* CheckUserdata(int index, const char* tname) const; void* CheckUserdata(int index, const char* tname) const;
void* CheckUserdata(int index, const NzString& tname) const; void* CheckUserdata(int index, const NzString& tname) const;
@ -71,19 +69,19 @@ class NAZARA_API NzLuaInstance : NzNonCopyable
bool ExecuteFromStream(NzInputStream& stream); bool ExecuteFromStream(NzInputStream& stream);
int GetAbsIndex(int index) const; int GetAbsIndex(int index) const;
void GetField(const char* fieldName, int index = -1) const; nzLuaType GetField(const char* fieldName, int index = -1) const;
void GetField(const NzString& fieldName, int index = -1) const; nzLuaType GetField(const NzString& fieldName, int index = -1) const;
void GetGlobal(const char* name) const; nzLuaType GetGlobal(const char* name) const;
void GetGlobal(const NzString& name) const; nzLuaType GetGlobal(const NzString& name) const;
lua_State* GetInternalState() const; lua_State* GetInternalState() const;
NzString GetLastError() const; NzString GetLastError() const;
nzUInt32 GetMemoryLimit() const; nzUInt32 GetMemoryLimit() const;
nzUInt32 GetMemoryUsage() const; nzUInt32 GetMemoryUsage() const;
void GetMetatable(const char* tname) const; nzLuaType GetMetatable(const char* tname) const;
void GetMetatable(const NzString& tname) const; nzLuaType GetMetatable(const NzString& tname) const;
bool GetMetatable(int index) const; bool GetMetatable(int index) const;
unsigned int GetStackTop() const; unsigned int GetStackTop() const;
void GetTable(int index = -2) const; nzLuaType GetTable(int index = -2) const;
nzUInt32 GetTimeLimit() const; nzUInt32 GetTimeLimit() const;
nzLuaType GetType(int index) const; nzLuaType GetType(int index) const;
const char* GetTypeName(nzLuaType type) const; const char* GetTypeName(nzLuaType type) const;
@ -108,7 +106,7 @@ class NAZARA_API NzLuaInstance : NzNonCopyable
void PushBoolean(bool value); void PushBoolean(bool value);
void PushCFunction(NzLuaCFunction func, int upvalueCount = 0); void PushCFunction(NzLuaCFunction func, int upvalueCount = 0);
void PushFunction(NzLuaFunction func); void PushFunction(NzLuaFunction func);
void PushInteger(int value); void PushInteger(long long value);
void PushLightUserdata(void* value); void PushLightUserdata(void* value);
void PushMetatable(const char* str); void PushMetatable(const char* str);
void PushMetatable(const NzString& str); void PushMetatable(const NzString& str);
@ -118,7 +116,6 @@ class NAZARA_API NzLuaInstance : NzNonCopyable
void PushString(const char* str); void PushString(const char* str);
void PushString(const NzString& str); void PushString(const NzString& str);
void PushTable(unsigned int sequenceElementCount = 0, unsigned int arrayElementCount = 0); void PushTable(unsigned int sequenceElementCount = 0, unsigned int arrayElementCount = 0);
void PushUnsigned(unsigned int value);
void* PushUserdata(unsigned int size); void* PushUserdata(unsigned int size);
void PushValue(int index); void PushValue(int index);
@ -137,11 +134,10 @@ class NAZARA_API NzLuaInstance : NzNonCopyable
void SetTimeLimit(nzUInt32 timeLimit); void SetTimeLimit(nzUInt32 timeLimit);
bool ToBoolean(int index) const; bool ToBoolean(int index) const;
int ToInteger(int index, bool* succeeded = nullptr) const; long long ToInteger(int index, bool* succeeded = nullptr) const;
double ToNumber(int index, bool* succeeded = nullptr) const; double ToNumber(int index, bool* succeeded = nullptr) const;
const void* ToPointer(int index) const; const void* ToPointer(int index) const;
const char* ToString(int index, std::size_t* length = nullptr) const; const char* ToString(int index, std::size_t* length = nullptr) const;
unsigned int ToUnsigned(int index, bool* succeeded = nullptr) const;
void* ToUserdata(int index) const; void* ToUserdata(int index) const;
void* ToUserdata(int index, const char* tname) const; void* ToUserdata(int index, const char* tname) const;
void* ToUserdata(int index, const NzString& tname) const; void* ToUserdata(int index, const NzString& tname) const;

View File

@ -369,15 +369,15 @@ inline NzString NzNumberToString(long long number, nzUInt8 radix)
do do
{ {
str += symbols[number % radix]; str.Append(symbols[number % radix]);
number /= radix; number /= radix;
} }
while (number > 0); while (number > 0);
if (negative) if (negative)
str += '-'; str.Append('-');
return str.Reversed(); return str.Reverse();
} }
template<typename T> template<typename T>

View File

@ -143,7 +143,7 @@
// Détection 64 bits // Détection 64 bits
#if !defined(NAZARA_PLATFORM_x64) && (defined(_WIN64) || defined(__amd64__) || defined(__x86_64__) || defined(__ia64__) || defined(__ia64) || \ #if !defined(NAZARA_PLATFORM_x64) && (defined(_WIN64) || defined(__amd64__) || defined(__x86_64__) || defined(__ia64__) || defined(__ia64) || \
defined(_M_IA64) || defined(__itanium__) || defined(__MINGW64__)) defined(_M_IA64) || defined(__itanium__) || defined(__MINGW64__) || defined(_M_AMD64) || defined (_M_X64))
#define NAZARA_PLATFORM_x64 #define NAZARA_PLATFORM_x64
#endif #endif

View File

@ -10,7 +10,7 @@
/// Ce fichier sert à vérifier la valeur des constantes du fichier Config.hpp /// Ce fichier sert à vérifier la valeur des constantes du fichier Config.hpp
#include <type_traits> #include <type_traits>
#define CheckTypeAndVal(name, type, op, val, err) static_assert(std::is_ ##type <decltype(name)>::value && name op val, #type err) #define NazaraCheckTypeAndVal(name, type, op, val, err) static_assert(std::is_ ##type <decltype(name)>::value && name op val, #type err)
// On force la valeur de MANAGE_MEMORY en mode debug // On force la valeur de MANAGE_MEMORY en mode debug
#if defined(NAZARA_DEBUG) && !NAZARA_RENDERER_MANAGE_MEMORY #if defined(NAZARA_DEBUG) && !NAZARA_RENDERER_MANAGE_MEMORY
@ -18,6 +18,8 @@
#define NAZARA_RENDERER_MANAGE_MEMORY 1 #define NAZARA_RENDERER_MANAGE_MEMORY 1
#endif #endif
CheckTypeAndVal(NAZARA_RENDERER_INSTANCE_BUFFER_SIZE, integral, >, 0, " shall be a strictly positive integer"); NazaraCheckTypeAndVal(NAZARA_RENDERER_INSTANCE_BUFFER_SIZE, integral, >, 0, " shall be a strictly positive integer");
#undef NazaraCheckTypeAndVal
#endif // NAZARA_CONFIG_CHECK_RENDERER_HPP #endif // NAZARA_CONFIG_CHECK_RENDERER_HPP

View File

@ -10,7 +10,7 @@
/// Ce fichier sert à vérifier la valeur des constantes du fichier Config.hpp /// Ce fichier sert à vérifier la valeur des constantes du fichier Config.hpp
#include <type_traits> #include <type_traits>
#define CheckTypeAndVal(name, type, op, val, err) static_assert(std::is_ ##type <decltype(name)>::value && name op val, #type err) #define NazaraCheckTypeAndVal(name, type, op, val, err) static_assert(std::is_ ##type <decltype(name)>::value && name op val, #type err)
// On force la valeur de MANAGE_MEMORY en mode debug // On force la valeur de MANAGE_MEMORY en mode debug
#if defined(NAZARA_DEBUG) && !NAZARA_UTILITY_MANAGE_MEMORY #if defined(NAZARA_DEBUG) && !NAZARA_UTILITY_MANAGE_MEMORY
@ -18,6 +18,8 @@
#define NAZARA_UTILITY_MANAGE_MEMORY 1 #define NAZARA_UTILITY_MANAGE_MEMORY 1
#endif #endif
CheckTypeAndVal(NAZARA_UTILITY_SKINNING_MAX_WEIGHTS, integral, >, 0, " shall be a strictly positive integer"); NazaraCheckTypeAndVal(NAZARA_UTILITY_SKINNING_MAX_WEIGHTS, integral, >, 0, " shall be a strictly positive integer");
#undef NazaraCheckTypeAndVal
#endif // NAZARA_CONFIG_CHECK_UTILITY_HPP #endif // NAZARA_CONFIG_CHECK_UTILITY_HPP

View File

@ -48,7 +48,6 @@ struct NAZARA_API NzMeshParams
bool IsValid() const; bool IsValid() const;
}; };
class NzAnimation;
class NzMesh; class NzMesh;
class NzPrimitiveList; class NzPrimitiveList;

View File

@ -3,6 +3,7 @@
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Error.hpp> #include <Nazara/Core/Error.hpp>
#include <algorithm>
#include <cstring> #include <cstring>
#include <Nazara/Utility/Debug.hpp> #include <Nazara/Utility/Debug.hpp>

View File

@ -88,6 +88,7 @@ namespace
nzAudioFormat GetFormat() const nzAudioFormat GetFormat() const
{ {
// Nous avons besoin du nombre de canaux d'origine pour convertir en mono, nous trichons donc un peu...
if (m_mixToMono) if (m_mixToMono)
return nzAudioFormat_Mono; return nzAudioFormat_Mono;
else else
@ -106,14 +107,16 @@ namespace
bool Open(const NzString& filePath, bool forceMono) bool Open(const NzString& filePath, bool forceMono)
{ {
// Nous devons gérer nous-même le flux car il doit rester ouvert après le passage du loader
// (les flux automatiquement ouverts par le ResourceLoader étant fermés après celui-ci)
std::unique_ptr<NzFile> file(new NzFile); std::unique_ptr<NzFile> file(new NzFile);
if (!file->Open(filePath, NzFile::ReadOnly)) if (!file->Open(filePath, NzFile::ReadOnly))
{ {
NazaraError("Failed to open stream from file: " + NzError::GetLastError()); NazaraError("Failed to open stream from file: " + NzError::GetLastError());
return false; return false;
} }
m_ownedStream = std::move(file);
m_ownedStream = std::move(file);
return Open(*m_ownedStream, forceMono); return Open(*m_ownedStream, forceMono);
} }
@ -126,7 +129,7 @@ namespace
bool Open(NzInputStream& stream, bool forceMono) bool Open(NzInputStream& stream, bool forceMono)
{ {
SF_INFO infos; SF_INFO infos;
infos.format = 0; infos.format = 0; // Format inconnu
m_handle = sf_open_virtual(&callbacks, SFM_READ, &infos, &stream); m_handle = sf_open_virtual(&callbacks, SFM_READ, &infos, &stream);
if (!m_handle) if (!m_handle)
@ -135,6 +138,7 @@ namespace
return false; return false;
} }
// Un peu de RAII
NzCallOnExit onExit([this] NzCallOnExit onExit([this]
{ {
sf_close(m_handle); sf_close(m_handle);
@ -151,6 +155,7 @@ namespace
m_sampleCount = infos.channels*infos.frames; m_sampleCount = infos.channels*infos.frames;
m_sampleRate = infos.samplerate; m_sampleRate = infos.samplerate;
// Durée de la musique (s) = samples / channels*rate
m_duration = 1000*m_sampleCount / (m_format*m_sampleRate); m_duration = 1000*m_sampleCount / (m_format*m_sampleRate);
// https://github.com/LaurentGomila/SFML/issues/271 // https://github.com/LaurentGomila/SFML/issues/271
@ -159,6 +164,7 @@ namespace
if (infos.format & SF_FORMAT_VORBIS) if (infos.format & SF_FORMAT_VORBIS)
sf_command(m_handle, SFC_SET_SCALE_FLOAT_INT_READ, nullptr, SF_TRUE); sf_command(m_handle, SFC_SET_SCALE_FLOAT_INT_READ, nullptr, SF_TRUE);
// On mixera en mono lors de la lecture
if (forceMono && m_format != nzAudioFormat_Mono) if (forceMono && m_format != nzAudioFormat_Mono)
{ {
m_mixToMono = true; m_mixToMono = true;
@ -174,8 +180,10 @@ namespace
unsigned int Read(void* buffer, unsigned int sampleCount) unsigned int Read(void* buffer, unsigned int sampleCount)
{ {
// Si la musique a été demandée en mono, nous devons la convertir à la volée lors de la lecture
if (m_mixToMono) if (m_mixToMono)
{ {
// On garde un buffer sur le côté pour éviter la réallocation
m_mixBuffer.resize(m_format*sampleCount); m_mixBuffer.resize(m_format*sampleCount);
unsigned int readSampleCount = sf_read_short(m_handle, m_mixBuffer.data(), m_format*sampleCount); unsigned int readSampleCount = sf_read_short(m_handle, m_mixBuffer.data(), m_format*sampleCount);
NzMixToMono(m_mixBuffer.data(), static_cast<nzInt16*>(buffer), m_format, sampleCount); NzMixToMono(m_mixBuffer.data(), static_cast<nzInt16*>(buffer), m_format, sampleCount);
@ -217,8 +225,9 @@ namespace
NazaraUnused(parameters); NazaraUnused(parameters);
SF_INFO info; SF_INFO info;
info.format = 0; info.format = 0; // Format inconnu
// Si on peut ouvrir le flux, c'est qu'il est dans un format compatible
SNDFILE* file = sf_open_virtual(&callbacks, SFM_READ, &info, &stream); SNDFILE* file = sf_open_virtual(&callbacks, SFM_READ, &info, &stream);
if (file) if (file)
{ {
@ -231,8 +240,6 @@ namespace
bool LoadMusicFile(NzMusic* music, const NzString& filePath, const NzMusicParams& parameters) bool LoadMusicFile(NzMusic* music, const NzString& filePath, const NzMusicParams& parameters)
{ {
NazaraUnused(parameters);
std::unique_ptr<sndfileStream> musicStream(new sndfileStream); std::unique_ptr<sndfileStream> musicStream(new sndfileStream);
if (!musicStream->Open(filePath, parameters.forceMono)) if (!musicStream->Open(filePath, parameters.forceMono))
{ {
@ -240,12 +247,13 @@ namespace
return false; return false;
} }
if (!music->Create(musicStream.get())) if (!music->Create(musicStream.get())) // Transfert de propriété
{ {
NazaraError("Failed to create music"); NazaraError("Failed to create music");
return false; return false;
} }
// Le pointeur a été transféré avec succès, nous pouvons laisser tomber la propriété
musicStream.release(); musicStream.release();
return true; return true;
@ -253,8 +261,6 @@ namespace
bool LoadMusicMemory(NzMusic* music, const void* data, std::size_t size, const NzMusicParams& parameters) bool LoadMusicMemory(NzMusic* music, const void* data, std::size_t size, const NzMusicParams& parameters)
{ {
NazaraUnused(parameters);
std::unique_ptr<sndfileStream> musicStream(new sndfileStream); std::unique_ptr<sndfileStream> musicStream(new sndfileStream);
if (!musicStream->Open(data, size, parameters.forceMono)) if (!musicStream->Open(data, size, parameters.forceMono))
{ {
@ -262,12 +268,13 @@ namespace
return false; return false;
} }
if (!music->Create(musicStream.get())) if (!music->Create(musicStream.get())) // Transfert de propriété
{ {
NazaraError("Failed to create music"); NazaraError("Failed to create music");
return false; return false;
} }
// Le pointeur a été transféré avec succès, nous pouvons laisser tomber la propriété
musicStream.release(); musicStream.release();
return true; return true;
@ -275,8 +282,6 @@ namespace
bool LoadMusicStream(NzMusic* music, NzInputStream& stream, const NzMusicParams& parameters) bool LoadMusicStream(NzMusic* music, NzInputStream& stream, const NzMusicParams& parameters)
{ {
NazaraUnused(parameters);
std::unique_ptr<sndfileStream> musicStream(new sndfileStream); std::unique_ptr<sndfileStream> musicStream(new sndfileStream);
if (!musicStream->Open(stream, parameters.forceMono)) if (!musicStream->Open(stream, parameters.forceMono))
{ {
@ -284,12 +289,13 @@ namespace
return false; return false;
} }
if (!music->Create(musicStream.get())) if (!music->Create(musicStream.get())) // Transfert de propriété
{ {
NazaraError("Failed to create music"); NazaraError("Failed to create music");
return false; return false;
} }
// Le pointeur a été transféré avec succès, nous pouvons laisser tomber la propriété
musicStream.release(); musicStream.release();
return true; return true;
@ -314,8 +320,6 @@ namespace
bool LoadSoundBuffer(NzSoundBuffer* soundBuffer, NzInputStream& stream, const NzSoundBufferParams& parameters) bool LoadSoundBuffer(NzSoundBuffer* soundBuffer, NzInputStream& stream, const NzSoundBufferParams& parameters)
{ {
NazaraUnused(parameters);
SF_INFO info; SF_INFO info;
info.format = 0; info.format = 0;
@ -326,7 +330,13 @@ namespace
return false; return false;
} }
NzCallOnExit onExit([file] { sf_close(file); }); // Lynix utilise RAII...
// C'est très efficace !
// MemoryLeak est confus...
NzCallOnExit onExit([file]
{
sf_close(file);
});
nzAudioFormat format = NzAudio::GetAudioFormat(info.channels); nzAudioFormat format = NzAudio::GetAudioFormat(info.channels);
if (format == nzAudioFormat_Unknown) if (format == nzAudioFormat_Unknown)
@ -341,7 +351,7 @@ namespace
if (info.format & SF_FORMAT_VORBIS) if (info.format & SF_FORMAT_VORBIS)
sf_command(file, SFC_SET_SCALE_FLOAT_INT_READ, nullptr, SF_TRUE); sf_command(file, SFC_SET_SCALE_FLOAT_INT_READ, nullptr, SF_TRUE);
sf_count_t sampleCount = info.frames * info.channels; unsigned int sampleCount = static_cast<unsigned int>(info.frames * info.channels);
std::unique_ptr<nzInt16[]> samples(new nzInt16[sampleCount]); std::unique_ptr<nzInt16[]> samples(new nzInt16[sampleCount]);
if (sf_read_short(file, samples.get(), sampleCount) != sampleCount) if (sf_read_short(file, samples.get(), sampleCount) != sampleCount)
@ -350,17 +360,17 @@ namespace
return false; return false;
} }
// Une conversion en mono est-elle nécessaire ?
if (parameters.forceMono && format != nzAudioFormat_Mono) if (parameters.forceMono && format != nzAudioFormat_Mono)
{ {
std::unique_ptr<nzInt16[]> monoSamples(new nzInt16[info.frames]); // Nous effectuons la conversion en mono dans le même buffer (il va de toute façon être copié)
NzMixToMono(samples.get(), monoSamples.get(), info.channels, info.frames); NzMixToMono(samples.get(), samples.get(), static_cast<unsigned int>(info.channels), static_cast<unsigned int>(info.frames));
format = nzAudioFormat_Mono; format = nzAudioFormat_Mono;
samples = std::move(monoSamples); sampleCount = static_cast<unsigned int>(info.frames);
sampleCount = info.frames;
} }
if (!soundBuffer->Create(format, static_cast<unsigned int>(sampleCount), info.samplerate, samples.get())) if (!soundBuffer->Create(format, sampleCount, info.samplerate, samples.get()))
{ {
NazaraError("Failed to create sound buffer"); NazaraError("Failed to create sound buffer");
return false; return false;

View File

@ -17,7 +17,7 @@
void NzError::Error(nzErrorType type, const NzString& error) void NzError::Error(nzErrorType type, const NzString& error)
{ {
if ((s_flags & nzErrorFlag_Silent) == 0 || (s_flags & nzErrorFlag_SilentDisabled) != 0) if (type == nzErrorType_AssertFailed || (s_flags & nzErrorFlag_Silent) == 0 || (s_flags & nzErrorFlag_SilentDisabled) != 0)
NazaraLog->WriteError(type, error); NazaraLog->WriteError(type, error);
s_lastError = error; s_lastError = error;
@ -27,16 +27,17 @@ void NzError::Error(nzErrorType type, const NzString& error)
#if NAZARA_CORE_EXIT_ON_ASSERT_FAILURE #if NAZARA_CORE_EXIT_ON_ASSERT_FAILURE
if (type == nzErrorType_AssertFailed) if (type == nzErrorType_AssertFailed)
std::exit(EXIT_FAILURE); std::abort();
#endif #endif
if (type != nzErrorType_Warning && (s_flags & nzErrorFlag_ThrowException) != 0 && (s_flags & nzErrorFlag_ThrowExceptionDisabled) == 0) if (type == nzErrorType_AssertFailed || (type != nzErrorType_Warning &&
(s_flags & nzErrorFlag_ThrowException) != 0 && (s_flags & nzErrorFlag_ThrowExceptionDisabled) == 0))
throw std::runtime_error(error); throw std::runtime_error(error);
} }
void NzError::Error(nzErrorType type, const NzString& error, unsigned int line, const char* file, const char* function) void NzError::Error(nzErrorType type, const NzString& error, unsigned int line, const char* file, const char* function)
{ {
if ((s_flags & nzErrorFlag_Silent) == 0 || (s_flags & nzErrorFlag_SilentDisabled) != 0) if (type == nzErrorType_AssertFailed || (s_flags & nzErrorFlag_Silent) == 0 || (s_flags & nzErrorFlag_SilentDisabled) != 0)
NazaraLog->WriteError(type, error, line, file, function); NazaraLog->WriteError(type, error, line, file, function);
s_lastError = error; s_lastError = error;
@ -44,13 +45,14 @@ void NzError::Error(nzErrorType type, const NzString& error, unsigned int line,
s_lastErrorFunction = function; s_lastErrorFunction = function;
s_lastErrorLine = line; s_lastErrorLine = line;
if (type != nzErrorType_Warning && (s_flags & nzErrorFlag_ThrowException) != 0 && (s_flags & nzErrorFlag_ThrowExceptionDisabled) == 0)
throw std::runtime_error(error);
#if NAZARA_CORE_EXIT_ON_ASSERT_FAILURE #if NAZARA_CORE_EXIT_ON_ASSERT_FAILURE
if (type == nzErrorType_AssertFailed) if (type == nzErrorType_AssertFailed)
std::exit(EXIT_FAILURE); std::abort();
#endif #endif
if (type == nzErrorType_AssertFailed || (type != nzErrorType_Warning &&
(s_flags & nzErrorFlag_ThrowException) != 0 && (s_flags & nzErrorFlag_ThrowExceptionDisabled) == 0))
throw std::runtime_error(error);
} }
nzUInt32 NzError::GetFlags() nzUInt32 NzError::GetFlags()

View File

@ -733,7 +733,7 @@ bool NzFile::FillHash(NzAbstractHash* hash) const
unsigned int size; unsigned int size;
while (remainingSize > 0) while (remainingSize > 0)
{ {
size = std::min(remainingSize, static_cast<nzUInt64>(NAZARA_CORE_FILE_BUFFERSIZE)); size = static_cast<unsigned int>(std::min(remainingSize, static_cast<nzUInt64>(NAZARA_CORE_FILE_BUFFERSIZE)));
if (file.Read(&buffer[0], sizeof(char), size) != sizeof(char)*size) if (file.Read(&buffer[0], sizeof(char), size) != sizeof(char)*size)
{ {
NazaraError("Unable to read file"); NazaraError("Unable to read file");

View File

@ -9,6 +9,7 @@
#include <Nazara/Core/GuillotineBinPack.hpp> #include <Nazara/Core/GuillotineBinPack.hpp>
#include <Nazara/Core/Config.hpp> #include <Nazara/Core/Config.hpp>
#include <algorithm> #include <algorithm>
#include <cstdlib>
#include <cmath> #include <cmath>
#include <limits> #include <limits>
#include <Nazara/Core/Debug.hpp> #include <Nazara/Core/Debug.hpp>
@ -22,8 +23,8 @@ namespace
int ScoreBestLongSideFit(int width, int height, const NzRectui& freeRectSize) int ScoreBestLongSideFit(int width, int height, const NzRectui& freeRectSize)
{ {
int leftoverHoriz = std::abs(freeRectSize.width - width); int leftoverHoriz = std::abs(static_cast<int>(freeRectSize.width - width));
int leftoverVert = std::abs(freeRectSize.height - height); int leftoverVert = std::abs(static_cast<int>(freeRectSize.height - height));
int leftover = std::max(leftoverHoriz, leftoverVert); int leftover = std::max(leftoverHoriz, leftoverVert);
return leftover; return leftover;
@ -31,8 +32,8 @@ namespace
int ScoreBestShortSideFit(int width, int height, const NzRectui& freeRectSize) int ScoreBestShortSideFit(int width, int height, const NzRectui& freeRectSize)
{ {
int leftoverHoriz = std::abs(freeRectSize.width - width); int leftoverHoriz = std::abs(static_cast<int>(freeRectSize.width - width));
int leftoverVert = std::abs(freeRectSize.height - height); int leftoverVert = std::abs(static_cast<int>(freeRectSize.height - height));
int leftover = std::min(leftoverHoriz, leftoverVert); int leftover = std::min(leftoverHoriz, leftoverVert);
return leftover; return leftover;

View File

@ -4,6 +4,7 @@
#include <Nazara/Core/HardwareInfo.hpp> #include <Nazara/Core/HardwareInfo.hpp>
#include <Nazara/Core/Error.hpp> #include <Nazara/Core/Error.hpp>
#include <algorithm>
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
@ -77,7 +78,11 @@ namespace
bool s_initialized = false; bool s_initialized = false;
char s_brandString[48] = "Not initialized"; char s_brandString[48] = "Not initialized";
char s_vendor[12] = {'C', 'P', 'U', 'i', 's', 'U', 'n', 'k', 'n', 'o', 'w', 'n'}; }
void NzHardwareInfo::Cpuid(nzUInt32 functionId, nzUInt32 subFunctionId, nzUInt32 result[4])
{
return NzHardwareInfoImpl::Cpuid(functionId, subFunctionId, result);
} }
NzString NzHardwareInfo::GetProcessorBrandString() NzString NzHardwareInfo::GetProcessorBrandString()
@ -137,67 +142,86 @@ bool NzHardwareInfo::Initialize()
s_initialized = true; s_initialized = true;
nzUInt32 result[4]; nzUInt32 registers[4]; // Récupère les quatre registres (EAX, EBX, ECX et EDX)
NzHardwareInfoImpl::Cpuid(0, result); // Pour plus de clarté
std::memcpy(&s_vendor[0], &result[1], 4); nzUInt32& eax = registers[0];
std::memcpy(&s_vendor[4], &result[3], 4); nzUInt32& ebx = registers[1];
std::memcpy(&s_vendor[8], &result[2], 4); nzUInt32& ecx = registers[2];
nzUInt32& edx = registers[3];
// Pour commencer, on va récupérer l'identifiant du constructeur ainsi que l'id de fonction maximal supporté par le CPUID
NzHardwareInfoImpl::Cpuid(0, 0, registers);
// Attention à l'ordre : EBX, EDX, ECX
nzUInt32 manufacturerId[3] = {ebx, edx, ecx};
// Identification du concepteur // Identification du concepteur
s_vendorEnum = nzProcessorVendor_Unknown; s_vendorEnum = nzProcessorVendor_Unknown;
for (const VendorString& vendorString : vendorStrings) for (const VendorString& vendorString : vendorStrings)
{ {
if (std::memcmp(s_vendor, vendorString.vendor, 12) == 0) if (std::memcmp(manufacturerId, vendorString.vendor, 12) == 0)
{ {
s_vendorEnum = vendorString.vendorEnum; s_vendorEnum = vendorString.vendorEnum;
break; break;
} }
} }
unsigned int ids = result[0]; if (eax >= 1)
if (ids >= 1)
{ {
NzHardwareInfoImpl::Cpuid(1, result); // Récupération de certaines capacités du processeur (ECX et EDX, fonction 1)
s_capabilities[nzProcessorCap_AVX] = (result[2] & (1U << 28)) != 0; NzHardwareInfoImpl::Cpuid(1, 0, registers);
s_capabilities[nzProcessorCap_FMA3] = (result[2] & (1U << 12)) != 0;
s_capabilities[nzProcessorCap_MMX] = (result[3] & (1U << 23)) != 0;
s_capabilities[nzProcessorCap_SSE] = (result[3] & (1U << 25)) != 0;
s_capabilities[nzProcessorCap_SSE2] = (result[3] & (1U << 26)) != 0;
s_capabilities[nzProcessorCap_SSE3] = (result[2] & (1U << 0)) != 0;
s_capabilities[nzProcessorCap_SSSE3] = (result[2] & (1U << 9)) != 0;
s_capabilities[nzProcessorCap_SSE41] = (result[2] & (1U << 19)) != 0;
s_capabilities[nzProcessorCap_SSE42] = (result[2] & (1U << 20)) != 0;
NzHardwareInfoImpl::Cpuid(0x80000000, result); s_capabilities[nzProcessorCap_AVX] = (ecx & (1U << 28)) != 0;
unsigned int exIds = result[0]; s_capabilities[nzProcessorCap_FMA3] = (ecx & (1U << 12)) != 0;
s_capabilities[nzProcessorCap_MMX] = (edx & (1U << 23)) != 0;
s_capabilities[nzProcessorCap_SSE] = (edx & (1U << 25)) != 0;
s_capabilities[nzProcessorCap_SSE2] = (edx & (1U << 26)) != 0;
s_capabilities[nzProcessorCap_SSE3] = (ecx & (1U << 0)) != 0;
s_capabilities[nzProcessorCap_SSSE3] = (ecx & (1U << 9)) != 0;
s_capabilities[nzProcessorCap_SSE41] = (ecx & (1U << 19)) != 0;
s_capabilities[nzProcessorCap_SSE42] = (ecx & (1U << 20)) != 0;
}
if (exIds >= 0x80000001) // Récupération de la plus grande fonction étendue supportée (EAX, fonction 0x80000000)
NzHardwareInfoImpl::Cpuid(0x80000000, 0, registers);
nzUInt32 maxSupportedExtendedFunction = eax;
if (maxSupportedExtendedFunction >= 0x80000001)
{
// Récupération des capacités étendues du processeur (ECX et EDX, fonction 0x80000001)
NzHardwareInfoImpl::Cpuid(0x80000001, 0, registers);
s_capabilities[nzProcessorCap_x64] = (edx & (1U << 29)) != 0; // Support du 64bits, indépendant de l'OS
s_capabilities[nzProcessorCap_FMA4] = (ecx & (1U << 16)) != 0;
s_capabilities[nzProcessorCap_SSE4a] = (ecx & (1U << 6)) != 0;
s_capabilities[nzProcessorCap_XOP] = (ecx & (1U << 11)) != 0;
if (maxSupportedExtendedFunction >= 0x80000004)
{ {
NzHardwareInfoImpl::Cpuid(0x80000001, result); // Récupération d'une chaîne de caractère décrivant le processeur (EAX, EBX, ECX et EDX,
s_capabilities[nzProcessorCap_x64] = (result[3] & (1U << 29)) != 0; // fonctions de 0x80000002 à 0x80000004 compris)
s_capabilities[nzProcessorCap_FMA4] = (result[2] & (1U << 16)) != 0; char* ptr = &s_brandString[0];
s_capabilities[nzProcessorCap_SSE4a] = (result[2] & (1U << 6)) != 0; for (nzUInt32 code = 0x80000002; code <= 0x80000004; ++code)
s_capabilities[nzProcessorCap_XOP] = (result[2] & (1U << 11)) != 0;
if (exIds >= 0x80000004)
{ {
char* ptr = &s_brandString[0]; NzHardwareInfoImpl::Cpuid(code, 0, registers);
for (nzUInt32 code = 0x80000002; code <= 0x80000004; ++code) std::memcpy(ptr, &registers[0], 4*sizeof(nzUInt32)); // On rajoute les 16 octets à la chaîne
{
NzHardwareInfoImpl::Cpuid(code, result);
std::memcpy(ptr, &result[0], 16);
ptr += 16; ptr += 4*sizeof(nzUInt32);
}
} }
// Le caractère nul faisant partie de la chaîne retournée par le CPUID, pas besoin de le rajouter
} }
} }
return true; return true;
} }
bool NzHardwareInfo::IsCpuidSupported()
{
return NzHardwareInfoImpl::IsCpuidSupported();
}
bool NzHardwareInfo::IsInitialized() bool NzHardwareInfo::IsInitialized()
{ {
return s_initialized; return s_initialized;

View File

@ -5,9 +5,9 @@
#include <Nazara/Core/HashDigest.hpp> #include <Nazara/Core/HashDigest.hpp>
#include <Nazara/Core/Config.hpp> #include <Nazara/Core/Config.hpp>
#include <Nazara/Core/Error.hpp> #include <Nazara/Core/Error.hpp>
#include <algorithm>
#include <cstdio> #include <cstdio>
#include <cstring> #include <cstring>
#include <utility>
#include <Nazara/Core/Debug.hpp> #include <Nazara/Core/Debug.hpp>
NzHashDigest::NzHashDigest() : NzHashDigest::NzHashDigest() :

View File

@ -91,7 +91,7 @@ bool NzParameterList::GetFloatParameter(const NzString& name, float* value) cons
return true; return true;
case nzParameterType_Integer: case nzParameterType_Integer:
*value = it->second.value.intVal; *value = static_cast<float>(it->second.value.intVal);
return true; return true;
case nzParameterType_String: case nzParameterType_String:
@ -99,7 +99,7 @@ bool NzParameterList::GetFloatParameter(const NzString& name, float* value) cons
double converted; double converted;
if (it->second.value.stringVal.ToDouble(&converted)) if (it->second.value.stringVal.ToDouble(&converted))
{ {
*value = converted; *value = static_cast<float>(converted);
return true; return true;
} }
@ -133,7 +133,7 @@ bool NzParameterList::GetIntegerParameter(const NzString& name, int* value) cons
return true; return true;
case nzParameterType_Float: case nzParameterType_Float:
*value = it->second.value.floatVal; *value = static_cast<int>(it->second.value.floatVal);
return true; return true;
case nzParameterType_Integer: case nzParameterType_Integer:
@ -147,7 +147,7 @@ bool NzParameterList::GetIntegerParameter(const NzString& name, int* value) cons
{ {
if (converted <= std::numeric_limits<int>::max() && converted >= std::numeric_limits<int>::min()) if (converted <= std::numeric_limits<int>::max() && converted >= std::numeric_limits<int>::min())
{ {
*value = converted; *value = static_cast<int>(converted);
return true; return true;
} }
} }

View File

@ -1,4 +1,4 @@
// Copyright (C) 2014 Alexandre Janniaux // Copyright (C) 2015 Alexandre Janniaux
// This file is part of the "Nazara Engine - Core module" // This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp

View File

@ -1776,96 +1776,63 @@ unsigned int NzString::GetSize() const
return m_sharedString->size; return m_sharedString->size;
} }
char* NzString::GetUtf8Buffer(unsigned int* size) const std::string NzString::GetUtf8String() const
{ {
if (m_sharedString->size == 0) return std::string(m_sharedString->string, m_sharedString->size);
return nullptr;
char* buffer = new char[m_sharedString->size+1];
std::memcpy(buffer, m_sharedString->string, m_sharedString->size+1);
if (size)
*size = m_sharedString->size;
return buffer;
} }
char16_t* NzString::GetUtf16Buffer(unsigned int* size) const std::u16string NzString::GetUtf16String() const
{ {
if (m_sharedString->size == 0) if (m_sharedString->size == 0)
return nullptr; return std::u16string();
std::vector<char16_t> utf16; std::u16string str;
utf16.reserve(m_sharedString->size); str.reserve(m_sharedString->size);
utf8::utf8to16(m_sharedString->string, &m_sharedString->string[m_sharedString->size], std::back_inserter(utf16)); utf8::utf8to16(begin(), end(), std::back_inserter(str));
unsigned int bufferSize = utf16.size(); return str;
if (bufferSize == 0)
return nullptr;
char16_t* buffer = new char16_t[bufferSize+1];
std::memcpy(buffer, &utf16[0], bufferSize*sizeof(char16_t));
buffer[bufferSize] ='\0';
if (size)
*size = bufferSize;
return buffer;
} }
char32_t* NzString::GetUtf32Buffer(unsigned int* size) const std::u32string NzString::GetUtf32String() const
{ {
if (m_sharedString->size == 0) if (m_sharedString->size == 0)
return nullptr; return std::u32string();
unsigned int bufferSize = utf8::distance(m_sharedString->string, &m_sharedString->string[m_sharedString->size]); std::u32string str;
if (bufferSize == 0) str.reserve(m_sharedString->size);
return nullptr;
char32_t* buffer = new char32_t[bufferSize+1]; utf8::utf8to32(begin(), end(), std::back_inserter(str));
utf8::utf8to32(m_sharedString->string, &m_sharedString->string[m_sharedString->size], buffer);
buffer[bufferSize] ='\0';
if (size) return str;
*size = bufferSize;
return buffer;
} }
wchar_t* NzString::GetWideBuffer(unsigned int* size) const std::wstring NzString::GetWideString() const
{ {
static_assert(sizeof(wchar_t) == 2 || sizeof(wchar_t) == 4, "wchar_t size is not supported"); static_assert(sizeof(wchar_t) == 2 || sizeof(wchar_t) == 4, "wchar_t size is not supported");
if (m_sharedString->size == 0) if (m_sharedString->size == 0)
return nullptr; return std::wstring();
unsigned int bufferSize = utf8::distance(m_sharedString->string, &m_sharedString->string[m_sharedString->size]); std::wstring str;
if (bufferSize == 0) str.reserve(m_sharedString->size);
return nullptr;
wchar_t* buffer = new wchar_t[bufferSize+1];
if (sizeof(wchar_t) == 4) // Je veux du static_if :( if (sizeof(wchar_t) == 4) // Je veux du static_if :(
utf8::utf8to32(m_sharedString->string, &m_sharedString->string[m_sharedString->size], buffer); utf8::utf8to32(begin(), end(), std::back_inserter(str));
else else
{ {
wchar_t* ptr = buffer;
utf8::unchecked::iterator<const char*> it(m_sharedString->string); utf8::unchecked::iterator<const char*> it(m_sharedString->string);
do do
{ {
char32_t cp = *it; char32_t cp = *it;
if (cp <= 0xFFFF && (cp < 0xD800 || cp > 0xDFFF)) // @Laurent Gomila if (cp <= 0xFFFF && (cp < 0xD800 || cp > 0xDFFF)) // @Laurent Gomila
*ptr++ = static_cast<wchar_t>(cp); str.push_back(static_cast<wchar_t>(cp));
else else
*ptr++ = L'?'; str.push_back(L'?');
} }
while (*it++); while (*it++);
} }
if (size) return str;
*size = bufferSize;
return buffer;
} }
NzString NzString::GetWord(unsigned int index, nzUInt32 flags) const NzString NzString::GetWord(unsigned int index, nzUInt32 flags) const
@ -3162,7 +3129,7 @@ NzString NzString::SubStringFrom(char character, int startPos, bool fromLast, bo
else else
pos = Find(character, startPos, flags); pos = Find(character, startPos, flags);
if (pos == 0 and include) if (pos == 0 && include)
return *this; return *this;
else if (pos == npos) else if (pos == npos)
return NzString(); return NzString();

View File

@ -6,6 +6,7 @@
#include <Nazara/Core/Config.hpp> #include <Nazara/Core/Config.hpp>
#include <Nazara/Core/Error.hpp> #include <Nazara/Core/Error.hpp>
#include <Nazara/Core/HardwareInfo.hpp> #include <Nazara/Core/HardwareInfo.hpp>
#include <ostream>
#include <stdexcept> #include <stdexcept>
#if defined(NAZARA_PLATFORM_WINDOWS) #if defined(NAZARA_PLATFORM_WINDOWS)

View File

@ -62,9 +62,7 @@ bool NzDirectoryImpl::Open(const NzString& dirPath)
{ {
NzString searchPath = dirPath + "\\*"; NzString searchPath = dirPath + "\\*";
std::unique_ptr<wchar_t[]> wPath(searchPath.GetWideBuffer()); m_handle = FindFirstFileW(searchPath.GetWideString().data(), &m_result);
m_handle = FindFirstFileW(wPath.get(), &m_result);
if (m_handle == INVALID_HANDLE_VALUE) if (m_handle == INVALID_HANDLE_VALUE)
{ {
NazaraError("Unable to open directory: " + NzError::GetLastSystemError()); NazaraError("Unable to open directory: " + NzError::GetLastSystemError());
@ -78,16 +76,12 @@ bool NzDirectoryImpl::Open(const NzString& dirPath)
bool NzDirectoryImpl::Create(const NzString& dirPath) bool NzDirectoryImpl::Create(const NzString& dirPath)
{ {
std::unique_ptr<wchar_t[]> wPath(dirPath.GetWideBuffer()); return (CreateDirectoryW(dirPath.GetWideString().data(), nullptr) != 0) || GetLastError() == ERROR_ALREADY_EXISTS;
return (CreateDirectoryW(wPath.get(), nullptr) != 0) || GetLastError() == ERROR_ALREADY_EXISTS;
} }
bool NzDirectoryImpl::Exists(const NzString& dirPath) bool NzDirectoryImpl::Exists(const NzString& dirPath)
{ {
std::unique_ptr<wchar_t[]> wPath(dirPath.GetWideBuffer()); DWORD attributes = GetFileAttributesW(dirPath.GetWideString().data());
DWORD attributes = GetFileAttributesW(wPath.get());
if (attributes != INVALID_FILE_ATTRIBUTES) if (attributes != INVALID_FILE_ATTRIBUTES)
return (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0; return (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
else else
@ -118,8 +112,7 @@ NzString NzDirectoryImpl::GetCurrent()
bool NzDirectoryImpl::Remove(const NzString& dirPath) bool NzDirectoryImpl::Remove(const NzString& dirPath)
{ {
std::unique_ptr<wchar_t[]> path(dirPath.GetWideBuffer()); bool success = RemoveDirectoryW(dirPath.GetWideString().data()) != 0;
bool success = RemoveDirectoryW(path.get()) != 0;
DWORD error = GetLastError(); DWORD error = GetLastError();
return success || error == ERROR_FILE_NOT_FOUND || error == ERROR_PATH_NOT_FOUND; return success || error == ERROR_FILE_NOT_FOUND || error == ERROR_PATH_NOT_FOUND;

View File

@ -30,9 +30,7 @@ bool NzDynLibImpl::Load(const NzString& libraryPath, NzString* errorMessage)
if (!path.EndsWith(".dll")) if (!path.EndsWith(".dll"))
path += ".dll"; path += ".dll";
std::unique_ptr<wchar_t[]> wPath(path.GetWideBuffer()); m_handle = LoadLibraryExW(path.GetWideString().data(), nullptr, (NzFile::IsAbsolute(path)) ? LOAD_WITH_ALTERED_SEARCH_PATH : 0);
m_handle = LoadLibraryExW(wPath.get(), nullptr, (NzFile::IsAbsolute(path)) ? LOAD_WITH_ALTERED_SEARCH_PATH : 0);
if (m_handle) if (m_handle)
return true; return true;
else else

View File

@ -92,9 +92,7 @@ bool NzFileImpl::Open(const NzString& filePath, unsigned int mode)
if ((mode & NzFile::Lock) == 0) if ((mode & NzFile::Lock) == 0)
shareMode |= FILE_SHARE_WRITE; shareMode |= FILE_SHARE_WRITE;
std::unique_ptr<wchar_t[]> path(filePath.GetWideBuffer()); m_handle = CreateFileW(filePath.GetWideString().data(), access, shareMode, nullptr, openMode, 0, nullptr);
m_handle = CreateFileW(path.get(), access, shareMode, nullptr, openMode, 0, nullptr);
return m_handle != INVALID_HANDLE_VALUE; return m_handle != INVALID_HANDLE_VALUE;
} }
@ -184,117 +182,96 @@ std::size_t NzFileImpl::Write(const void* buffer, std::size_t size)
bool NzFileImpl::Copy(const NzString& sourcePath, const NzString& targetPath) bool NzFileImpl::Copy(const NzString& sourcePath, const NzString& targetPath)
{ {
std::unique_ptr<wchar_t[]> srcPath(sourcePath.GetWideBuffer()); if (CopyFileW(sourcePath.GetWideString().data(), targetPath.GetWideString().data(), false))
std::unique_ptr<wchar_t[]> dstPath(targetPath.GetWideBuffer());
if (CopyFileW(srcPath.get(), dstPath.get(), false))
return true; return true;
else else
{ {
NazaraError("Failed to copy file: " + NzError::GetLastSystemError()); NazaraError("Failed to copy file: " + NzError::GetLastSystemError());
return false; return false;
} }
} }
bool NzFileImpl::Delete(const NzString& filePath) bool NzFileImpl::Delete(const NzString& filePath)
{ {
std::unique_ptr<wchar_t[]> path(filePath.GetWideBuffer()); if (DeleteFileW(filePath.GetWideString().data()))
if (DeleteFileW(path.get()))
return true; return true;
else else
{ {
NazaraError("Failed to delete file (" + filePath + "): " + NzError::GetLastSystemError()); NazaraError("Failed to delete file (" + filePath + "): " + NzError::GetLastSystemError());
return false; return false;
} }
} }
bool NzFileImpl::Exists(const NzString& filePath) bool NzFileImpl::Exists(const NzString& filePath)
{ {
std::unique_ptr<wchar_t[]> path(filePath.GetWideBuffer()); HANDLE handle = CreateFileW(filePath.GetWideString().data(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr);
HANDLE handle = CreateFileW(path.get(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr);
if (handle == INVALID_HANDLE_VALUE) if (handle == INVALID_HANDLE_VALUE)
return false; return false;
CloseHandle(handle); CloseHandle(handle);
return true; return true;
} }
time_t NzFileImpl::GetCreationTime(const NzString& filePath) time_t NzFileImpl::GetCreationTime(const NzString& filePath)
{ {
std::unique_ptr<wchar_t[]> path(filePath.GetWideBuffer()); HANDLE handle = CreateFileW(filePath.GetWideString().data(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr);
HANDLE handle = CreateFileW(path.get(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr);
if (handle == INVALID_HANDLE_VALUE) if (handle == INVALID_HANDLE_VALUE)
return 0; return 0;
FILETIME creationTime; FILETIME creationTime;
if (!GetFileTime(handle, &creationTime, nullptr, nullptr)) if (!GetFileTime(handle, &creationTime, nullptr, nullptr))
{ {
NazaraError("Unable to get creation time: " + NzError::GetLastSystemError());
CloseHandle(handle); CloseHandle(handle);
NazaraError("Unable to get creation time: " + NzError::GetLastSystemError());
return 0; return 0;
} }
CloseHandle(handle); CloseHandle(handle);
return NzFileTimeToTime(&creationTime); return NzFileTimeToTime(&creationTime);
} }
time_t NzFileImpl::GetLastAccessTime(const NzString& filePath) time_t NzFileImpl::GetLastAccessTime(const NzString& filePath)
{ {
std::unique_ptr<wchar_t[]> path(filePath.GetWideBuffer()); HANDLE handle = CreateFileW(filePath.GetWideString().data(), 0, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
HANDLE handle = CreateFileW(path.get(), 0, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
if (handle == INVALID_HANDLE_VALUE) if (handle == INVALID_HANDLE_VALUE)
return 0; return 0;
FILETIME accessTime; FILETIME accessTime;
if (!GetFileTime(handle, nullptr, &accessTime, nullptr)) if (!GetFileTime(handle, nullptr, &accessTime, nullptr))
{ {
NazaraError("Unable to get last access time: " + NzError::GetLastSystemError());
CloseHandle(handle); CloseHandle(handle);
NazaraError("Unable to get last access time: " + NzError::GetLastSystemError());
return 0; return 0;
} }
CloseHandle(handle); CloseHandle(handle);
return NzFileTimeToTime(&accessTime); return NzFileTimeToTime(&accessTime);
} }
time_t NzFileImpl::GetLastWriteTime(const NzString& filePath) time_t NzFileImpl::GetLastWriteTime(const NzString& filePath)
{ {
std::unique_ptr<wchar_t[]> path(filePath.GetWideBuffer()); HANDLE handle = CreateFileW(filePath.GetWideString().data(), 0, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
HANDLE handle = CreateFileW(path.get(), 0, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
if (handle == INVALID_HANDLE_VALUE) if (handle == INVALID_HANDLE_VALUE)
return 0; return 0;
FILETIME writeTime; FILETIME writeTime;
if (!GetFileTime(handle, nullptr, nullptr, &writeTime)) if (!GetFileTime(handle, nullptr, nullptr, &writeTime))
{ {
NazaraError("Unable to get last write time: " + NzError::GetLastSystemError());
CloseHandle(handle); CloseHandle(handle);
NazaraError("Unable to get last write time: " + NzError::GetLastSystemError());
return 0; return 0;
} }
CloseHandle(handle); CloseHandle(handle);
return NzFileTimeToTime(&writeTime); return NzFileTimeToTime(&writeTime);
} }
nzUInt64 NzFileImpl::GetSize(const NzString& filePath) nzUInt64 NzFileImpl::GetSize(const NzString& filePath)
{ {
std::unique_ptr<wchar_t[]> path(filePath.GetWideBuffer()); HANDLE handle = CreateFileW(filePath.GetWideString().data(), 0, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
HANDLE handle = CreateFileW(path.get(), 0, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
if (handle == INVALID_HANDLE_VALUE) if (handle == INVALID_HANDLE_VALUE)
return 0; return 0;
@ -303,16 +280,12 @@ nzUInt64 NzFileImpl::GetSize(const NzString& filePath)
fileSize.QuadPart = 0; fileSize.QuadPart = 0;
CloseHandle(handle); CloseHandle(handle);
return fileSize.QuadPart; return fileSize.QuadPart;
} }
bool NzFileImpl::Rename(const NzString& sourcePath, const NzString& targetPath) bool NzFileImpl::Rename(const NzString& sourcePath, const NzString& targetPath)
{ {
std::unique_ptr<wchar_t[]> srcPath(sourcePath.GetWideBuffer()); if (MoveFileExW(sourcePath.GetWideString().data(), targetPath.GetWideString().data(), MOVEFILE_COPY_ALLOWED))
std::unique_ptr<wchar_t[]> dstPath(targetPath.GetWideBuffer());
if (MoveFileExW(srcPath.get(), dstPath.get(), MOVEFILE_COPY_ALLOWED))
return true; return true;
else else
{ {

View File

@ -12,15 +12,18 @@
#include <Nazara/Core/Debug.hpp> #include <Nazara/Core/Debug.hpp>
void NzHardwareInfoImpl::Cpuid(nzUInt32 code, nzUInt32 result[4]) void NzHardwareInfoImpl::Cpuid(nzUInt32 functionId, nzUInt32 subFunctionId, nzUInt32 registers[4])
{ {
#if defined(NAZARA_COMPILER_MSVC) #if defined(NAZARA_COMPILER_MSVC)
__cpuid(reinterpret_cast<int*>(result), static_cast<int>(code)); // Visual propose une fonction intrinsèque pour le cpuid static_assert(sizeof(nzUInt32) == sizeof(int), "Assertion failed");
// Visual propose une fonction intrinsèque pour le cpuid
__cpuidex(reinterpret_cast<int*>(registers), static_cast<int>(functionId), static_cast<int>(subFunctionId));
#elif defined(NAZARA_COMPILER_CLANG) || defined(NAZARA_COMPILER_GCC) || defined(NAZARA_COMPILER_INTEL) #elif defined(NAZARA_COMPILER_CLANG) || defined(NAZARA_COMPILER_GCC) || defined(NAZARA_COMPILER_INTEL)
// Source: http://stackoverflow.com/questions/1666093/cpuid-implementations-in-c // Source: http://stackoverflow.com/questions/1666093/cpuid-implementations-in-c
asm volatile ("cpuid" // Besoin d'être volatile ? asm volatile ("cpuid" // Besoin d'être volatile ?
: "=a" (result[0]), "=b" (result[1]), "=c" (result[2]), "=d" (result[3]) // output : "=a" (registers[0]), "=b" (registers[1]), "=c" (registers[2]), "=d" (registers[3]) // output
: "a" (code), "c" (0)); // input : "a" (functionId), "c" (subFunctionId)); // input
#else #else
NazaraInternalError("Cpuid has been called although it is not supported"); NazaraInternalError("Cpuid has been called although it is not supported");
#endif #endif
@ -37,10 +40,10 @@ unsigned int NzHardwareInfoImpl::GetProcessorCount()
bool NzHardwareInfoImpl::IsCpuidSupported() bool NzHardwareInfoImpl::IsCpuidSupported()
{ {
#if defined(NAZARA_COMPILER_MSVC) #ifdef NAZARA_PLATFORM_x64
#ifdef NAZARA_PLATFORM_x64
return true; // Toujours supporté sur un processeur 64 bits return true; // Toujours supporté sur un processeur 64 bits
#else #else
#if defined(NAZARA_COMPILER_MSVC)
int supported; int supported;
__asm __asm
{ {
@ -59,31 +62,27 @@ bool NzHardwareInfoImpl::IsCpuidSupported()
}; };
return supported != 0; return supported != 0;
#endif // NAZARA_PLATFORM_x64 #elif defined(NAZARA_COMPILER_CLANG) || defined(NAZARA_COMPILER_GCC) || defined(NAZARA_COMPILER_INTEL)
#elif defined(NAZARA_COMPILER_CLANG) || defined(NAZARA_COMPILER_GCC) || defined(NAZARA_COMPILER_INTEL)
#ifdef NAZARA_PLATFORM_x64
return true; // Toujours supporté sur un processeur 64 bits
#else
int supported; int supported;
asm volatile (" pushfl\n" asm volatile (" pushfl\n"
" pop %%eax\n" " pop %%eax\n"
" mov %%eax, %%ecx\n" " mov %%eax, %%ecx\n"
" xor $0x200000, %%eax\n" " xor $0x200000, %%eax\n"
" push %%eax\n" " push %%eax\n"
" popfl\n" " popfl\n"
" pushfl\n" " pushfl\n"
" pop %%eax\n" " pop %%eax\n"
" xor %%ecx, %%eax\n" " xor %%ecx, %%eax\n"
" mov %%eax, %0\n" " mov %%eax, %0\n"
" push %%ecx\n" " push %%ecx\n"
" popfl" " popfl"
: "=m" (supported) // output : "=m" (supported) // output
: // input : // input
: "eax", "ecx", "memory"); // clobbered register : "eax", "ecx", "memory"); // clobbered register
return supported != 0; return supported != 0;
#endif // NAZARA_PLATFORM_x64 #else
#else
return false; return false;
#endif
#endif #endif
} }

View File

@ -12,7 +12,7 @@
class NzHardwareInfoImpl class NzHardwareInfoImpl
{ {
public: public:
static void Cpuid(nzUInt32 code, nzUInt32 result[4]); static void Cpuid(nzUInt32 functionId, nzUInt32 subFunctionId, nzUInt32 registers[4]);
static unsigned int GetProcessorCount(); static unsigned int GetProcessorCount();
static bool IsCpuidSupported(); static bool IsCpuidSupported();
}; };

View File

@ -177,7 +177,7 @@ bool NzDeferredGeometryPass::Resize(const NzVector2ui& dimensions)
/* /*
G-Buffer: G-Buffer:
Texture0: Diffuse Color + Flags Texture0: Diffuse Color + Flags
Texture1: Normal map + Depth Texture1: Encoded normal
Texture2: Specular value + Shininess Texture2: Specular value + Shininess
Texture3: N/A Texture3: N/A
*/ */

View File

@ -3,6 +3,8 @@
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Graphics/Loaders/OBJ.hpp> #include <Nazara/Graphics/Loaders/OBJ.hpp>
#include <Nazara/Core/Algorithm.hpp>
#include <Nazara/Core/ErrorFlags.hpp>
#include <Nazara/Graphics/Material.hpp> #include <Nazara/Graphics/Material.hpp>
#include <Nazara/Graphics/Model.hpp> #include <Nazara/Graphics/Model.hpp>
#include <Nazara/Graphics/Loaders/OBJ/MTLParser.hpp> #include <Nazara/Graphics/Loaders/OBJ/MTLParser.hpp>
@ -16,6 +18,8 @@
#include <unordered_map> #include <unordered_map>
#include <Nazara/Graphics/Debug.hpp> #include <Nazara/Graphics/Debug.hpp>
///TODO: N'avoir qu'un seul VertexBuffer communs à tous les meshes
namespace namespace
{ {
bool IsSupported(const NzString& extension) bool IsSupported(const NzString& extension)
@ -31,10 +35,97 @@ namespace
return nzTernary_Unknown; return nzTernary_Unknown;
} }
bool LoadMaterials(NzModel* model, const NzString& filePath, const NzMaterialParams& parameters, const NzString* materials, const NzOBJParser::Mesh* meshes, unsigned int meshCount)
{
NzFile file(filePath);
if (!file.Open(NzFile::ReadOnly | NzFile::Text))
{
NazaraError("Failed to open MTL file (" + file.GetPath() + ')');
return false;
}
NzMTLParser materialParser(file);
if (!materialParser.Parse())
{
NazaraError("MTL parser failed");
return false;
}
std::unordered_map<NzString, NzMaterialRef> materialCache;
NzString baseDir = file.GetDirectory();
for (unsigned int i = 0; i < meshCount; ++i)
{
const NzString& matName = materials[meshes[i].material];
const NzMTLParser::Material* mtlMat = materialParser.GetMaterial(matName);
if (!mtlMat)
{
NazaraWarning("MTL has no material \"" + matName + '"');
continue;
}
auto it = materialCache.find(matName);
if (it == materialCache.end())
{
NzMaterialRef material = NzMaterial::New();
material->SetShader(parameters.shaderName);
nzUInt8 alphaValue = static_cast<nzUInt8>(mtlMat->alpha*255.f);
NzColor ambientColor(mtlMat->ambient);
NzColor diffuseColor(mtlMat->diffuse);
NzColor specularColor(mtlMat->specular);
ambientColor.a = alphaValue;
diffuseColor.a = alphaValue;
specularColor.a = alphaValue;
material->SetAmbientColor(ambientColor);
material->SetDiffuseColor(diffuseColor);
material->SetSpecularColor(specularColor);
material->SetShininess(mtlMat->shininess);
bool isTranslucent = (alphaValue != 255);
if (parameters.loadAlphaMap && !mtlMat->alphaMap.IsEmpty())
{
if (material->SetAlphaMap(baseDir + mtlMat->alphaMap))
isTranslucent = true; // Une alpha map indique de la transparence
else
NazaraWarning("Failed to load alpha map (" + mtlMat->alphaMap + ')');
}
if (parameters.loadDiffuseMap && !mtlMat->diffuseMap.IsEmpty())
{
if (!material->SetDiffuseMap(baseDir + mtlMat->diffuseMap))
NazaraWarning("Failed to load diffuse map (" + mtlMat->diffuseMap + ')');
}
if (parameters.loadSpecularMap && !mtlMat->specularMap.IsEmpty())
{
if (!material->SetSpecularMap(baseDir + mtlMat->specularMap))
NazaraWarning("Failed to load specular map (" + mtlMat->specularMap + ')');
}
// Si nous avons une alpha map ou des couleurs transparentes,
// nous devons configurer le matériau pour accepter la transparence au mieux
if (isTranslucent)
{
// On paramètre le matériau pour accepter la transparence au mieux
material->Enable(nzRendererParameter_Blend, true);
material->Enable(nzRendererParameter_DepthWrite, false);
material->SetDstBlend(nzBlendFunc_InvSrcAlpha);
material->SetSrcBlend(nzBlendFunc_SrcAlpha);
}
it = materialCache.emplace(matName, std::move(material)).first;
}
model->SetMaterial(meshes[i].material, it->second);
}
}
bool Load(NzModel* model, NzInputStream& stream, const NzModelParameters& parameters) bool Load(NzModel* model, NzInputStream& stream, const NzModelParameters& parameters)
{ {
NzOBJParser parser(stream); NzOBJParser parser(stream);
if (!parser.Parse()) if (!parser.Parse())
{ {
NazaraError("OBJ parser failed"); NazaraError("OBJ parser failed");
@ -53,10 +144,15 @@ namespace
const NzVector3f* normals = parser.GetNormals(); const NzVector3f* normals = parser.GetNormals();
const NzVector3f* texCoords = parser.GetTexCoords(); const NzVector3f* texCoords = parser.GetTexCoords();
std::vector<unsigned int> faceIndices;
const NzOBJParser::Mesh* meshes = parser.GetMeshes(); const NzOBJParser::Mesh* meshes = parser.GetMeshes();
unsigned int meshCount = parser.GetMeshCount(); unsigned int meshCount = parser.GetMeshCount();
NazaraAssert(materials != nullptr && positions != nullptr && normals != nullptr &&
texCoords != nullptr && meshes != nullptr && meshCount > 0,
"Invalid OBJParser output");
// Un conteneur temporaire pour contenir les indices de face avant triangulation
std::vector<unsigned int> faceIndices(3); // Comme il y aura au moins trois sommets
for (unsigned int i = 0; i < meshCount; ++i) for (unsigned int i = 0; i < meshCount; ++i)
{ {
unsigned int faceCount = meshes[i].faces.size(); unsigned int faceCount = meshes[i].faces.size();
@ -66,8 +162,35 @@ namespace
std::vector<unsigned int> indices; std::vector<unsigned int> indices;
indices.reserve(faceCount*3); // Pire cas si les faces sont des triangles indices.reserve(faceCount*3); // Pire cas si les faces sont des triangles
// Bien plus rapide qu'un vector (pour la recherche) // Afin d'utiliser OBJParser::FaceVertex comme clé dans un unordered_map,
std::unordered_map<int, std::unordered_map<int, std::unordered_map<int, unsigned int>>> vertices; // nous devons fournir un foncteur de hash ainsi qu'un foncteur de comparaison
// Hash
struct FaceVertexHasher
{
std::size_t operator()(const NzOBJParser::FaceVertex& o) const
{
std::size_t seed = 0;
NzHashCombine(seed, o.normal);
NzHashCombine(seed, o.position);
NzHashCombine(seed, o.texCoord);
return seed;
}
};
// Comparaison
struct FaceVertexComparator
{
bool operator()(const NzOBJParser::FaceVertex& lhs, const NzOBJParser::FaceVertex& rhs) const
{
return lhs.normal == rhs.normal &&
lhs.position == rhs.position &&
lhs.texCoord == rhs.texCoord;
}
};
std::unordered_map<NzOBJParser::FaceVertex, unsigned int, FaceVertexHasher, FaceVertexComparator> vertices;
unsigned int vertexCount = 0; unsigned int vertexCount = 0;
for (unsigned int j = 0; j < faceCount; ++j) for (unsigned int j = 0; j < faceCount; ++j)
@ -79,15 +202,11 @@ namespace
{ {
const NzOBJParser::FaceVertex& vertex = meshes[i].faces[j].vertices[k]; const NzOBJParser::FaceVertex& vertex = meshes[i].faces[j].vertices[k];
auto& map = vertices[vertex.texCoord][vertex.normal]; auto it = vertices.find(vertex);
auto it = map.find(vertex.position); if (it == vertices.end())
if (it == map.end()) it = vertices.emplace(vertex, vertexCount++).first;
{
faceIndices[k] = vertexCount; faceIndices[k] = it->second;
map[vertex.position] = vertexCount++;
}
else
faceIndices[k] = it->second;
} }
for (unsigned int k = 1; k < faceVertexCount-1; ++k) for (unsigned int k = 1; k < faceVertexCount-1; ++k)
@ -114,36 +233,29 @@ namespace
bool hasTexCoords = true; bool hasTexCoords = true;
NzBufferMapper<NzVertexBuffer> vertexMapper(vertexBuffer, nzBufferAccess_WriteOnly); NzBufferMapper<NzVertexBuffer> vertexMapper(vertexBuffer, nzBufferAccess_WriteOnly);
NzMeshVertex* meshVertices = static_cast<NzMeshVertex*>(vertexMapper.GetPointer()); NzMeshVertex* meshVertices = static_cast<NzMeshVertex*>(vertexMapper.GetPointer());
for (auto& uvIt : vertices) for (auto& vertexPair : vertices)
{ {
for (auto& normalIt : uvIt.second) const NzOBJParser::FaceVertex& vertexIndices = vertexPair.first;
unsigned int index = vertexPair.second;
NzMeshVertex& vertex = meshVertices[index];
const NzVector4f& vec = positions[vertexIndices.position];
vertex.position.Set(vec.x, vec.y, vec.z);
vertex.position *= parameters.mesh.scale/vec.w;
if (vertexIndices.normal >= 0)
vertex.normal = normals[vertexIndices.normal];
else
hasNormals = false;
if (vertexIndices.texCoord >= 0)
{ {
for (auto& positionIt : normalIt.second) const NzVector3f& uvw = texCoords[vertexIndices.texCoord];
{ vertex.uv.Set(uvw.x, (parameters.mesh.flipUVs) ? 1.f - uvw.y : uvw.y); // Inversion des UVs si demandé
NzMeshVertex& vertex = meshVertices[positionIt.second];
const NzVector4f& vec = positions[positionIt.first];
vertex.position.Set(vec.x, vec.y, vec.z);
vertex.position *= parameters.mesh.scale/vec.w;
int index;
index = normalIt.first; // Normale
if (index >= 0)
vertex.normal = normals[index];
else
hasNormals = false;
index = uvIt.first; // Coordonnées de texture
if (index >= 0)
{
const NzVector3f& uvw = texCoords[index];
vertex.uv.Set(uvw.x, (parameters.mesh.flipUVs) ? 1.f - uvw.y : uvw.y); // Inversion des UVs si demandé
}
else
hasTexCoords = false;
}
} }
else
hasTexCoords = false;
} }
vertexMapper.Unmap(); vertexMapper.Unmap();
@ -184,90 +296,8 @@ namespace
NzString mtlLib = parser.GetMtlLib(); NzString mtlLib = parser.GetMtlLib();
if (parameters.loadMaterials && !mtlLib.IsEmpty()) if (parameters.loadMaterials && !mtlLib.IsEmpty())
{ {
NzFile file(stream.GetDirectory() + mtlLib); NzErrorFlags flags(nzErrorFlag_ThrowExceptionDisabled);
if (file.Open(NzFile::ReadOnly | NzFile::Text)) LoadMaterials(model, stream.GetDirectory() + mtlLib, parameters.material, materials, meshes, meshCount);
{
NzMTLParser materialParser(file);
if (materialParser.Parse())
{
std::unordered_map<NzString, NzMaterialRef> materialCache;
NzString baseDir = file.GetDirectory();
for (unsigned int i = 0; i < meshCount; ++i)
{
const NzString& matName = materials[meshes[i].material];
const NzMTLParser::Material* mtlMat = materialParser.GetMaterial(matName);
if (mtlMat)
{
auto it = materialCache.find(matName);
if (it != materialCache.end())
model->SetMaterial(meshes[i].material, it->second);
else
{
NzMaterialRef material = NzMaterial::New();
material->SetShader(parameters.material.shaderName);
nzUInt8 alphaValue = static_cast<nzUInt8>(mtlMat->alpha*255.f);
NzColor ambientColor(mtlMat->ambient);
ambientColor.a = alphaValue;
NzColor diffuseColor(mtlMat->diffuse);
diffuseColor.a = alphaValue;
NzColor specularColor(mtlMat->specular);
specularColor.a = alphaValue;
material->SetAmbientColor(ambientColor);
material->SetDiffuseColor(diffuseColor);
material->SetSpecularColor(specularColor);
material->SetShininess(mtlMat->shininess);
bool hasAlphaMap = false;;
if (parameters.material.loadAlphaMap && !mtlMat->alphaMap.IsEmpty())
{
if (material->SetAlphaMap(baseDir + mtlMat->alphaMap))
hasAlphaMap = true;
else
NazaraWarning("Failed to load alpha map (" + mtlMat->alphaMap + ')');
}
if (parameters.material.loadDiffuseMap && !mtlMat->diffuseMap.IsEmpty())
{
if (!material->SetDiffuseMap(baseDir + mtlMat->diffuseMap))
NazaraWarning("Failed to load diffuse map (" + mtlMat->diffuseMap + ')');
}
if (parameters.material.loadSpecularMap && !mtlMat->specularMap.IsEmpty())
{
if (!material->SetSpecularMap(baseDir + mtlMat->specularMap))
NazaraWarning("Failed to load specular map (" + mtlMat->specularMap + ')');
}
// Si nous avons une alpha map ou des couleurs transparentes,
// nous devons configurer le matériau pour accepter la transparence au mieux
if (hasAlphaMap || alphaValue != 255)
{
// On paramètre le matériau pour accepter la transparence au mieux
material->Enable(nzRendererParameter_Blend, true);
material->Enable(nzRendererParameter_DepthWrite, false);
material->SetDstBlend(nzBlendFunc_InvSrcAlpha);
material->SetSrcBlend(nzBlendFunc_SrcAlpha);
}
materialCache[matName] = material;
model->SetMaterial(meshes[i].material, material);
}
}
else
NazaraWarning("MTL has no material \"" + matName + '"');
}
}
else
NazaraWarning("MTL parser failed");
}
else
NazaraWarning("Failed to open MTL file (" + file.GetPath() + ')');
} }
return true; return true;

View File

@ -6,7 +6,7 @@
#include <Nazara/Core/Error.hpp> #include <Nazara/Core/Error.hpp>
#include <Nazara/Core/Log.hpp> #include <Nazara/Core/Log.hpp>
#include <Nazara/Utility/Config.hpp> #include <Nazara/Utility/Config.hpp>
#include <cstdio> #include <cctype>
#include <memory> #include <memory>
#include <unordered_map> #include <unordered_map>
#include <Nazara/Graphics/Debug.hpp> #include <Nazara/Graphics/Debug.hpp>

View File

@ -406,23 +406,23 @@ void NzMaterial::Reset()
SetShader("Basic"); SetShader("Basic");
} }
bool NzMaterial::SetAlphaMap(const NzString& name) bool NzMaterial::SetAlphaMap(const NzString& textureName)
{ {
NzTextureRef texture = NzTextureLibrary::Query(name); NzTextureRef texture = NzTextureLibrary::Query(textureName);
if (!texture) if (!texture)
{ {
texture = NzTextureManager::Get(name); texture = NzTextureManager::Get(textureName);
if (!texture) if (!texture)
return false; return false;
} }
SetAlphaMap(texture); SetAlphaMap(std::move(texture));
return true; return true;
} }
void NzMaterial::SetAlphaMap(NzTexture* map) void NzMaterial::SetAlphaMap(NzTextureRef alphaMap)
{ {
m_alphaMap = map; m_alphaMap = std::move(alphaMap);
InvalidateShaders(); InvalidateShaders();
} }
@ -447,23 +447,23 @@ void NzMaterial::SetDiffuseColor(const NzColor& diffuse)
m_diffuseColor = diffuse; m_diffuseColor = diffuse;
} }
bool NzMaterial::SetDiffuseMap(const NzString& name) bool NzMaterial::SetDiffuseMap(const NzString& textureName)
{ {
NzTextureRef texture = NzTextureLibrary::Query(name); NzTextureRef texture = NzTextureLibrary::Query(textureName);
if (!texture) if (!texture)
{ {
texture = NzTextureManager::Get(name); texture = NzTextureManager::Get(textureName);
if (!texture) if (!texture)
return false; return false;
} }
SetDiffuseMap(texture); SetDiffuseMap(std::move(texture));
return true; return true;
} }
void NzMaterial::SetDiffuseMap(NzTexture* map) void NzMaterial::SetDiffuseMap(NzTextureRef diffuseMap)
{ {
m_diffuseMap = map; m_diffuseMap = std::move(diffuseMap);
InvalidateShaders(); InvalidateShaders();
} }
@ -478,23 +478,23 @@ void NzMaterial::SetDstBlend(nzBlendFunc func)
m_states.dstBlend = func; m_states.dstBlend = func;
} }
bool NzMaterial::SetEmissiveMap(const NzString& name) bool NzMaterial::SetEmissiveMap(const NzString& textureName)
{ {
NzTextureRef texture = NzTextureLibrary::Query(name); NzTextureRef texture = NzTextureLibrary::Query(textureName);
if (!texture) if (!texture)
{ {
texture = NzTextureManager::Get(name); texture = NzTextureManager::Get(textureName);
if (!texture) if (!texture)
return false; return false;
} }
SetEmissiveMap(texture); SetEmissiveMap(std::move(texture));
return true; return true;
} }
void NzMaterial::SetEmissiveMap(NzTexture* map) void NzMaterial::SetEmissiveMap(NzTextureRef emissiveMap)
{ {
m_emissiveMap = map; m_emissiveMap = std::move(emissiveMap);
InvalidateShaders(); InvalidateShaders();
} }
@ -509,44 +509,44 @@ void NzMaterial::SetFaceFilling(nzFaceFilling filling)
m_states.faceFilling = filling; m_states.faceFilling = filling;
} }
bool NzMaterial::SetHeightMap(const NzString& name) bool NzMaterial::SetHeightMap(const NzString& textureName)
{ {
NzTextureRef texture = NzTextureLibrary::Query(name); NzTextureRef texture = NzTextureLibrary::Query(textureName);
if (!texture) if (!texture)
{ {
texture = NzTextureManager::Get(name); texture = NzTextureManager::Get(textureName);
if (!texture) if (!texture)
return false; return false;
} }
SetHeightMap(texture); SetHeightMap(std::move(texture));
return true; return true;
} }
void NzMaterial::SetHeightMap(NzTexture* map) void NzMaterial::SetHeightMap(NzTextureRef heightMap)
{ {
m_heightMap = map; m_heightMap = std::move(heightMap);
InvalidateShaders(); InvalidateShaders();
} }
bool NzMaterial::SetNormalMap(const NzString& name) bool NzMaterial::SetNormalMap(const NzString& textureName)
{ {
NzTextureRef texture = NzTextureLibrary::Query(name); NzTextureRef texture = NzTextureLibrary::Query(textureName);
if (!texture) if (!texture)
{ {
texture = NzTextureManager::Get(name); texture = NzTextureManager::Get(textureName);
if (!texture) if (!texture)
return false; return false;
} }
SetNormalMap(texture); SetNormalMap(std::move(texture));
return true; return true;
} }
void NzMaterial::SetNormalMap(NzTexture* map) void NzMaterial::SetNormalMap(NzTextureRef normalMap)
{ {
m_normalMap = map; m_normalMap = std::move(normalMap);
InvalidateShaders(); InvalidateShaders();
} }
@ -556,20 +556,20 @@ void NzMaterial::SetRenderStates(const NzRenderStates& states)
m_states = states; m_states = states;
} }
void NzMaterial::SetShader(const NzUberShader* uberShader) void NzMaterial::SetShader(NzUberShaderConstRef uberShader)
{ {
m_uberShader = uberShader; m_uberShader = std::move(uberShader);
InvalidateShaders(); InvalidateShaders();
} }
bool NzMaterial::SetShader(const NzString& uberShaderName) bool NzMaterial::SetShader(const NzString& uberShaderName)
{ {
NzUberShader* uberShader = NzUberShaderLibrary::Get(uberShaderName); NzUberShaderConstRef uberShader = NzUberShaderLibrary::Get(uberShaderName);
if (!uberShader) if (!uberShader)
return false; return false;
SetShader(uberShader); SetShader(std::move(uberShader));
return true; return true;
} }
@ -583,23 +583,23 @@ void NzMaterial::SetSpecularColor(const NzColor& specular)
m_specularColor = specular; m_specularColor = specular;
} }
bool NzMaterial::SetSpecularMap(const NzString& name) bool NzMaterial::SetSpecularMap(const NzString& textureName)
{ {
NzTextureRef texture = NzTextureLibrary::Query(name); NzTextureRef texture = NzTextureLibrary::Query(textureName);
if (!texture) if (!texture)
{ {
texture = NzTextureManager::Get(name); texture = NzTextureManager::Get(textureName);
if (!texture) if (!texture)
return false; return false;
} }
SetSpecularMap(texture); SetSpecularMap(std::move(texture));
return true; return true;
} }
void NzMaterial::SetSpecularMap(NzTexture* map) void NzMaterial::SetSpecularMap(NzTextureRef specularMap)
{ {
m_specularMap = map; m_specularMap = std::move(specularMap);
InvalidateShaders(); InvalidateShaders();
} }

View File

@ -81,12 +81,12 @@ void NzScene::Draw()
if (m_renderTechniqueRanking > 0) if (m_renderTechniqueRanking > 0)
{ {
m_renderTechnique.reset(NzRenderTechniques::GetByRanking(m_renderTechniqueRanking-1, &m_renderTechniqueRanking)); m_renderTechnique.reset(NzRenderTechniques::GetByRanking(m_renderTechniqueRanking-1, &m_renderTechniqueRanking));
NazaraError("Render technique \"" + oldName + "\" failed, falling back to \"" + m_renderTechnique->GetName() + '"'); NazaraError("Render technique \"" + oldName + "\" failed (" + NzString(e.what()) + "), falling back to \"" + m_renderTechnique->GetName() + '"');
} }
else else
{ {
NzErrorFlags errFlags(nzErrorFlag_ThrowException); NzErrorFlags errFlags(nzErrorFlag_ThrowException);
NazaraError("Render technique \"" + oldName + "\" failed and no fallback is available"); NazaraError("Render technique \"" + oldName + "\" failed (" + NzString(e.what()) + ") and no fallback is available");
} }
return; return;

View File

@ -44,7 +44,8 @@ m_nextFrame(model.m_nextFrame)
NzSkeletalModel::~NzSkeletalModel() NzSkeletalModel::~NzSkeletalModel()
{ {
m_scene->UnregisterForUpdate(this); if (m_scene)
m_scene->UnregisterForUpdate(this);
} }
void NzSkeletalModel::AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const void NzSkeletalModel::AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const

View File

@ -333,6 +333,7 @@ bool NzTextSprite::OnAtlasLayerChange(const NzAbstractAtlas* atlas, NzAbstractIm
NzTexture* oldTexture = static_cast<NzTexture*>(oldLayer); NzTexture* oldTexture = static_cast<NzTexture*>(oldLayer);
NzTexture* newTexture = static_cast<NzTexture*>(newLayer); NzTexture* newTexture = static_cast<NzTexture*>(newLayer);
// Il est possible que nous n'utilisions pas la texture en question (l'atlas nous prévenant pour chacun de ses layers)
auto it = m_renderInfos.find(oldTexture); auto it = m_renderInfos.find(oldTexture);
if (it != m_renderInfos.end()) if (it != m_renderInfos.end())
{ {
@ -343,7 +344,7 @@ bool NzTextSprite::OnAtlasLayerChange(const NzAbstractAtlas* atlas, NzAbstractIm
NzVector2ui newSize(newTexture->GetSize()); NzVector2ui newSize(newTexture->GetSize());
NzVector2f scale = NzVector2f(oldSize)/NzVector2f(newSize); // ratio ancienne et nouvelle taille NzVector2f scale = NzVector2f(oldSize)/NzVector2f(newSize); // ratio ancienne et nouvelle taille
// On va maintenant parcourir toutes les coordonnées de texture pour les multiplier par ce ratio // On va maintenant parcourir toutes les coordonnées de texture concernées pour les multiplier par ce ratio
NzSparsePtr<NzVector2f> texCoordPtr(&m_vertices[indices.first].uv, sizeof(NzVertexStruct_XYZ_Color_UV)); NzSparsePtr<NzVector2f> texCoordPtr(&m_vertices[indices.first].uv, sizeof(NzVertexStruct_XYZ_Color_UV));
for (unsigned int i = 0; i < indices.count; ++i) for (unsigned int i = 0; i < indices.count; ++i)
{ {
@ -372,7 +373,7 @@ void NzTextSprite::OnAtlasReleased(const NzAbstractAtlas* atlas, void* userdata)
#endif #endif
// L'atlas a été libéré alors que le TextSprite l'utilisait encore, notre seule option (pour éviter un crash) est de nous réinitialiser // L'atlas a été libéré alors que le TextSprite l'utilisait encore, notre seule option (pour éviter un crash) est de nous réinitialiser
NazaraWarning("TextSprite " + NzString::Pointer(this) + " has been cleared because atlas " + NzString::Pointer(atlas) + " that was under use has been released"); NazaraWarning("TextSprite " + NzString::Pointer(this) + " has been cleared because atlas " + NzString::Pointer(atlas) + " has been released");
Clear(); Clear();
} }

View File

@ -13,8 +13,10 @@ m_targetRegion(0.f, 0.f, 1.f, 1.f),
m_size(0.f), m_size(0.f),
m_target(nullptr), m_target(nullptr),
m_frustumUpdated(false), m_frustumUpdated(false),
m_invViewProjMatrixUpdated(false),
m_projectionMatrixUpdated(false), m_projectionMatrixUpdated(false),
m_viewMatrixUpdated(false), m_viewMatrixUpdated(false),
m_viewProjMatrixUpdated(false),
m_viewportUpdated(false), m_viewportUpdated(false),
m_zFar(1.f), m_zFar(1.f),
m_zNear(-1.f) m_zNear(-1.f)
@ -95,6 +97,14 @@ NzVector3f NzView::GetGlobalUp() const
return -NzVector3f::UnitY(); return -NzVector3f::UnitY();
} }
const NzMatrix4f& NzView::GetInvViewProjMatrix() const
{
if (!m_invViewProjMatrixUpdated)
UpdateInvViewProjMatrix();
return m_invViewProjMatrix;
}
const NzMatrix4f& NzView::GetProjectionMatrix() const const NzMatrix4f& NzView::GetProjectionMatrix() const
{ {
if (!m_projectionMatrixUpdated) if (!m_projectionMatrixUpdated)
@ -121,6 +131,14 @@ const NzMatrix4f& NzView::GetViewMatrix() const
return m_viewMatrix; return m_viewMatrix;
} }
const NzMatrix4f& NzView::GetViewProjMatrix() const
{
if (!m_viewProjMatrixUpdated)
UpdateViewProjMatrix();
return m_viewProjMatrix;
}
const NzRecti& NzView::GetViewport() const const NzRecti& NzView::GetViewport() const
{ {
#if NAZARA_GRAPHICS_SAFE #if NAZARA_GRAPHICS_SAFE
@ -147,6 +165,44 @@ float NzView::GetZNear() const
return m_zNear; return m_zNear;
} }
NzVector2i NzView::MapWorldToPixel(const NzVector2f& coords)
{
if (!m_viewProjMatrixUpdated)
UpdateViewProjMatrix();
if (!m_viewportUpdated)
UpdateViewport();
// Conversion du viewport en flottant
NzRectf viewport(m_viewport);
NzVector2f normalized = m_viewProjMatrix.Transform(coords);
NzVector2i pixel;
pixel.x = static_cast<int>(( normalized.x + 1.f) * viewport.width / 2.f + viewport.x);
pixel.y = static_cast<int>((-normalized.y + 1.f) * viewport.width / 2.f + viewport.y);
return pixel;
}
NzVector2f NzView::MapPixelToWorld(const NzVector2i& pixel)
{
if (!m_invViewProjMatrixUpdated)
UpdateInvViewProjMatrix();
if (!m_viewportUpdated)
UpdateViewport();
// Conversion du viewport en flottant
NzRectf viewport(m_viewport);
NzVector2f normalized;
normalized.x = -1.f + 2.f * (pixel.x - viewport.x) / viewport.width;
normalized.y = 1.f - 2.f * (pixel.y - viewport.y) / viewport.height;
return m_invViewProjMatrix.Transform(normalized);
}
void NzView::SetSize(const NzVector2f& size) void NzView::SetSize(const NzVector2f& size)
{ {
SetSize(size.x, size.y); SetSize(size.x, size.y);
@ -178,7 +234,9 @@ void NzView::SetTargetRegion(const NzRectf& region)
m_targetRegion = region; m_targetRegion = region;
m_frustumUpdated = false; m_frustumUpdated = false;
m_invViewProjMatrixUpdated = false;
m_projectionMatrixUpdated = false; m_projectionMatrixUpdated = false;
m_viewProjMatrixUpdated = false;
m_viewportUpdated = false; m_viewportUpdated = false;
} }
@ -204,7 +262,9 @@ void NzView::SetZFar(float zFar)
m_zFar = zFar; m_zFar = zFar;
m_frustumUpdated = false; m_frustumUpdated = false;
m_invViewProjMatrixUpdated = false;
m_projectionMatrixUpdated = false; m_projectionMatrixUpdated = false;
m_viewProjMatrixUpdated = false;
} }
void NzView::SetZNear(float zNear) void NzView::SetZNear(float zNear)
@ -212,7 +272,9 @@ void NzView::SetZNear(float zNear)
m_zNear = zNear; m_zNear = zNear;
m_frustumUpdated = false; m_frustumUpdated = false;
m_invViewProjMatrixUpdated = false;
m_projectionMatrixUpdated = false; m_projectionMatrixUpdated = false;
m_viewProjMatrixUpdated = false;
} }
void NzView::ApplyView() const void NzView::ApplyView() const
@ -246,7 +308,9 @@ void NzView::InvalidateNode()
// Le frustum et la view matrix dépendent des paramètres du node, invalidons-les // Le frustum et la view matrix dépendent des paramètres du node, invalidons-les
m_frustumUpdated = false; m_frustumUpdated = false;
m_invViewProjMatrixUpdated = false;
m_viewMatrixUpdated = false; m_viewMatrixUpdated = false;
m_viewProjMatrixUpdated = false;
} }
void NzView::OnRenderTargetReleased(const NzRenderTarget* renderTarget, void* userdata) void NzView::OnRenderTargetReleased(const NzRenderTarget* renderTarget, void* userdata)
@ -287,6 +351,15 @@ void NzView::UpdateFrustum() const
m_frustumUpdated = true; m_frustumUpdated = true;
} }
void NzView::UpdateInvViewProjMatrix() const
{
if (!m_viewProjMatrixUpdated)
UpdateViewProjMatrix();
m_viewProjMatrix.GetInverseAffine(&m_invViewProjMatrix);
m_invViewProjMatrixUpdated = true;
}
void NzView::UpdateProjectionMatrix() const void NzView::UpdateProjectionMatrix() const
{ {
if (m_size.x <= 0.f || m_size.y <= 0.f) // Si la taille est nulle, on prendra la taille du viewport if (m_size.x <= 0.f || m_size.y <= 0.f) // Si la taille est nulle, on prendra la taille du viewport
@ -294,7 +367,7 @@ void NzView::UpdateProjectionMatrix() const
if (!m_viewportUpdated) if (!m_viewportUpdated)
UpdateViewport(); UpdateViewport();
m_projectionMatrix.MakeOrtho(0.f, m_viewport.width, 0.f, m_viewport.height, m_zNear, m_zFar); m_projectionMatrix.MakeOrtho(0.f, static_cast<float>(m_viewport.width), 0.f, static_cast<float>(m_viewport.height), m_zNear, m_zFar);
} }
else else
m_projectionMatrix.MakeOrtho(0.f, m_size.x, 0.f, m_size.y, m_zNear, m_zFar); m_projectionMatrix.MakeOrtho(0.f, m_size.x, 0.f, m_size.y, m_zNear, m_zFar);
@ -311,6 +384,19 @@ void NzView::UpdateViewMatrix() const
m_viewMatrixUpdated = true; m_viewMatrixUpdated = true;
} }
void NzView::UpdateViewProjMatrix() const
{
if (!m_projectionMatrixUpdated)
UpdateProjectionMatrix();
if (!m_viewMatrixUpdated)
UpdateViewMatrix();
// La matrice de projection orthogonale est affine
m_viewProjMatrix = NzMatrix4f::ConcatenateAffine(m_viewMatrix, m_projectionMatrix);
m_viewProjMatrixUpdated = true;
}
void NzView::UpdateViewport() const void NzView::UpdateViewport() const
{ {
unsigned int width = m_target->GetWidth(); unsigned int width = m_target->GetWidth();

View File

@ -19,6 +19,45 @@
namespace namespace
{ {
nzLuaType FromLuaType(int type)
{
switch (type)
{
case LUA_TBOOLEAN:
return nzLuaType_Boolean;
case LUA_TFUNCTION:
return nzLuaType_Function;
case LUA_TLIGHTUSERDATA:
return nzLuaType_LightUserdata;
case LUA_TNIL:
return nzLuaType_Nil;
case LUA_TNONE:
return nzLuaType_None;
case LUA_TNUMBER:
return nzLuaType_Number;
case LUA_TSTRING:
return nzLuaType_String;
case LUA_TTABLE:
return nzLuaType_Table;
case LUA_TTHREAD:
return nzLuaType_Thread;
case LUA_TUSERDATA:
return nzLuaType_Userdata;
default:
return nzLuaType_None;
}
}
struct StreamData struct StreamData
{ {
NzInputStream* stream; NzInputStream* stream;
@ -134,7 +173,7 @@ bool NzLuaInstance::CheckBoolean(int index) const
return false; return false;
} }
return lua_toboolean(m_state, index); return lua_toboolean(m_state, index) != 0;
} }
bool NzLuaInstance::CheckBoolean(int index, bool defValue) const bool NzLuaInstance::CheckBoolean(int index, bool defValue) const
@ -142,17 +181,17 @@ bool NzLuaInstance::CheckBoolean(int index, bool defValue) const
if (lua_isnoneornil(m_state, index)) if (lua_isnoneornil(m_state, index))
return defValue; return defValue;
return lua_toboolean(m_state, index); return lua_toboolean(m_state, index) != 0;
} }
int NzLuaInstance::CheckInteger(int index) const long long NzLuaInstance::CheckInteger(int index) const
{ {
return luaL_checkint(m_state, index); return luaL_checkinteger(m_state, index);
} }
int NzLuaInstance::CheckInteger(int index, int defValue) const long long NzLuaInstance::CheckInteger(int index, long long defValue) const
{ {
return luaL_optint(m_state, index, defValue); return luaL_optinteger(m_state, index, defValue);
} }
double NzLuaInstance::CheckNumber(int index) const double NzLuaInstance::CheckNumber(int index) const
@ -198,16 +237,6 @@ void NzLuaInstance::CheckType(int index, nzLuaType type) const
luaL_checktype(m_state, index, s_types[type]); luaL_checktype(m_state, index, s_types[type]);
} }
unsigned int NzLuaInstance::CheckUnsigned(int index) const
{
return luaL_checkunsigned(m_state, index);
}
unsigned int NzLuaInstance::CheckUnsigned(int index, unsigned int defValue) const
{
return luaL_optunsigned(m_state, index, defValue);
}
void* NzLuaInstance::CheckUserdata(int index, const char* tname) const void* NzLuaInstance::CheckUserdata(int index, const char* tname) const
{ {
return luaL_checkudata(m_state, index, tname); return luaL_checkudata(m_state, index, tname);
@ -228,7 +257,7 @@ bool NzLuaInstance::Compare(int index1, int index2, nzLuaComparison comparison)
} }
#endif #endif
return (lua_compare(m_state, index1, index2, s_comparisons[comparison]) == 1); return (lua_compare(m_state, index1, index2, s_comparisons[comparison]) != 0);
} }
void NzLuaInstance::Compute(nzLuaOperation operation) void NzLuaInstance::Compute(nzLuaOperation operation)
@ -395,24 +424,24 @@ int NzLuaInstance::GetAbsIndex(int index) const
return lua_absindex(m_state, index); return lua_absindex(m_state, index);
} }
void NzLuaInstance::GetField(const char* fieldName, int index) const nzLuaType NzLuaInstance::GetField(const char* fieldName, int index) const
{ {
lua_getfield(m_state, index, fieldName); return FromLuaType(lua_getfield(m_state, index, fieldName));
} }
void NzLuaInstance::GetField(const NzString& fieldName, int index) const nzLuaType NzLuaInstance::GetField(const NzString& fieldName, int index) const
{ {
lua_getfield(m_state, index, fieldName.GetConstBuffer()); return FromLuaType(lua_getfield(m_state, index, fieldName.GetConstBuffer()));
} }
void NzLuaInstance::GetGlobal(const char* name) const nzLuaType NzLuaInstance::GetGlobal(const char* name) const
{ {
lua_getglobal(m_state, name); return FromLuaType(lua_getglobal(m_state, name));
} }
void NzLuaInstance::GetGlobal(const NzString& name) const nzLuaType NzLuaInstance::GetGlobal(const NzString& name) const
{ {
lua_getglobal(m_state, name.GetConstBuffer()); return FromLuaType(lua_getglobal(m_state, name.GetConstBuffer()));
} }
lua_State* NzLuaInstance::GetInternalState() const lua_State* NzLuaInstance::GetInternalState() const
@ -435,19 +464,19 @@ nzUInt32 NzLuaInstance::GetMemoryUsage() const
return m_memoryUsage; return m_memoryUsage;
} }
void NzLuaInstance::GetMetatable(const char* tname) const nzLuaType NzLuaInstance::GetMetatable(const char* tname) const
{ {
luaL_getmetatable(m_state, tname); return FromLuaType(luaL_getmetatable(m_state, tname));
} }
void NzLuaInstance::GetMetatable(const NzString& tname) const nzLuaType NzLuaInstance::GetMetatable(const NzString& tname) const
{ {
luaL_getmetatable(m_state, tname.GetConstBuffer()); return FromLuaType(luaL_getmetatable(m_state, tname.GetConstBuffer()));
} }
bool NzLuaInstance::GetMetatable(int index) const bool NzLuaInstance::GetMetatable(int index) const
{ {
return lua_getmetatable(m_state, index) == 1; return lua_getmetatable(m_state, index) != 0;
} }
unsigned int NzLuaInstance::GetStackTop() const unsigned int NzLuaInstance::GetStackTop() const
@ -455,9 +484,9 @@ unsigned int NzLuaInstance::GetStackTop() const
return lua_gettop(m_state); return lua_gettop(m_state);
} }
void NzLuaInstance::GetTable(int index) const nzLuaType NzLuaInstance::GetTable(int index) const
{ {
lua_gettable(m_state, index); return FromLuaType(lua_gettable(m_state, index));
} }
nzUInt32 NzLuaInstance::GetTimeLimit() const nzUInt32 NzLuaInstance::GetTimeLimit() const
@ -467,41 +496,7 @@ nzUInt32 NzLuaInstance::GetTimeLimit() const
nzLuaType NzLuaInstance::GetType(int index) const nzLuaType NzLuaInstance::GetType(int index) const
{ {
switch (lua_type(m_state, index)) return FromLuaType(lua_type(m_state, index));
{
case LUA_TBOOLEAN:
return nzLuaType_Boolean;
case LUA_TFUNCTION:
return nzLuaType_Function;
case LUA_TLIGHTUSERDATA:
return nzLuaType_LightUserdata;
case LUA_TNIL:
return nzLuaType_Nil;
case LUA_TNONE:
return nzLuaType_None;
case LUA_TNUMBER:
return nzLuaType_Number;
case LUA_TSTRING:
return nzLuaType_String;
case LUA_TTABLE:
return nzLuaType_Table;
case LUA_TTHREAD:
return nzLuaType_Thread;
case LUA_TUSERDATA:
return nzLuaType_Userdata;
default:
return nzLuaType_None;
}
} }
const char* NzLuaInstance::GetTypeName(nzLuaType type) const const char* NzLuaInstance::GetTypeName(nzLuaType type) const
@ -527,34 +522,34 @@ bool NzLuaInstance::IsOfType(int index, nzLuaType type) const
switch (type) switch (type)
{ {
case nzLuaType_Boolean: case nzLuaType_Boolean:
return lua_isboolean(m_state, index) == 1; return lua_isboolean(m_state, index) != 0;
case nzLuaType_Function: case nzLuaType_Function:
return lua_isfunction(m_state, index) == 1; return lua_isfunction(m_state, index) != 0;
case nzLuaType_LightUserdata: case nzLuaType_LightUserdata:
return lua_islightuserdata(m_state, index) == 1; return lua_islightuserdata(m_state, index) != 0;
case nzLuaType_Nil: case nzLuaType_Nil:
return lua_isnil(m_state, index) == 1; return lua_isnil(m_state, index) != 0;
case nzLuaType_None: case nzLuaType_None:
return lua_isnone(m_state, index) == 1; return lua_isnone(m_state, index) != 0;
case nzLuaType_Number: case nzLuaType_Number:
return lua_isnumber(m_state, index) == 1; return lua_isnumber(m_state, index) != 0;
case nzLuaType_String: case nzLuaType_String:
return lua_isstring(m_state, index) == 1; return lua_isstring(m_state, index) != 0;
case nzLuaType_Table: case nzLuaType_Table:
return lua_istable(m_state, index) == 1; return lua_istable(m_state, index) != 0;
case nzLuaType_Thread: case nzLuaType_Thread:
return lua_isthread(m_state, index) == 1; return lua_isthread(m_state, index) != 0;
case nzLuaType_Userdata: case nzLuaType_Userdata:
return lua_isuserdata(m_state, index) == 1; return lua_isuserdata(m_state, index) != 0;
} }
NazaraError("Lua type not handled (0x" + NzString::Number(type, 16) + ')'); NazaraError("Lua type not handled (0x" + NzString::Number(type, 16) + ')');
@ -574,7 +569,7 @@ bool NzLuaInstance::IsOfType(int index, const NzString& tname) const
bool NzLuaInstance::IsValid(int index) const bool NzLuaInstance::IsValid(int index) const
{ {
return !lua_isnoneornil(m_state, index); return lua_isnoneornil(m_state, index) == 0;
} }
unsigned int NzLuaInstance::Length(int index) const unsigned int NzLuaInstance::Length(int index) const
@ -589,17 +584,17 @@ void NzLuaInstance::MoveTo(NzLuaInstance* instance, int n)
bool NzLuaInstance::NewMetatable(const char* str) bool NzLuaInstance::NewMetatable(const char* str)
{ {
return luaL_newmetatable(m_state, str) == 1; return luaL_newmetatable(m_state, str) != 0;
} }
bool NzLuaInstance::NewMetatable(const NzString& str) bool NzLuaInstance::NewMetatable(const NzString& str)
{ {
return luaL_newmetatable(m_state, str.GetConstBuffer()); return luaL_newmetatable(m_state, str.GetConstBuffer()) != 0;
} }
bool NzLuaInstance::Next(int index) bool NzLuaInstance::Next(int index)
{ {
return lua_next(m_state, index) == 1; return lua_next(m_state, index) != 0;
} }
void NzLuaInstance::Pop(unsigned int n) void NzLuaInstance::Pop(unsigned int n)
@ -609,7 +604,7 @@ void NzLuaInstance::Pop(unsigned int n)
void NzLuaInstance::PushBoolean(bool value) void NzLuaInstance::PushBoolean(bool value)
{ {
lua_pushboolean(m_state, value); lua_pushboolean(m_state, (value) ? 1 : 0);
} }
void NzLuaInstance::PushCFunction(NzLuaCFunction func, int upvalueCount) void NzLuaInstance::PushCFunction(NzLuaCFunction func, int upvalueCount)
@ -625,7 +620,7 @@ void NzLuaInstance::PushFunction(NzLuaFunction func)
lua_pushcclosure(m_state, ProxyFunc, 1); lua_pushcclosure(m_state, ProxyFunc, 1);
} }
void NzLuaInstance::PushInteger(int value) void NzLuaInstance::PushInteger(long long value)
{ {
lua_pushinteger(m_state, value); lua_pushinteger(m_state, value);
} }
@ -675,11 +670,6 @@ void NzLuaInstance::PushTable(unsigned int sequenceElementCount, unsigned int ar
lua_createtable(m_state, sequenceElementCount, arrayElementCount); lua_createtable(m_state, sequenceElementCount, arrayElementCount);
} }
void NzLuaInstance::PushUnsigned(unsigned int value)
{
lua_pushunsigned(m_state, value);
}
void* NzLuaInstance::PushUserdata(unsigned int size) void* NzLuaInstance::PushUserdata(unsigned int size)
{ {
return lua_newuserdata(m_state, size); return lua_newuserdata(m_state, size);
@ -760,16 +750,16 @@ void NzLuaInstance::SetTimeLimit(nzUInt32 timeLimit)
bool NzLuaInstance::ToBoolean(int index) const bool NzLuaInstance::ToBoolean(int index) const
{ {
return lua_toboolean(m_state, index); return lua_toboolean(m_state, index) != 0;
} }
int NzLuaInstance::ToInteger(int index, bool* succeeded) const long long NzLuaInstance::ToInteger(int index, bool* succeeded) const
{ {
int success; int success;
int result = lua_tointegerx(m_state, index, &success); long long result = lua_tointegerx(m_state, index, &success);
if (succeeded) if (succeeded)
*succeeded = (success == 1); *succeeded = (success != 0);
return result; return result;
} }
@ -780,7 +770,7 @@ double NzLuaInstance::ToNumber(int index, bool* succeeded) const
double result = lua_tonumberx(m_state, index, &success); double result = lua_tonumberx(m_state, index, &success);
if (succeeded) if (succeeded)
*succeeded = (success == 1); *succeeded = (success != 0);
return result; return result;
} }
@ -795,17 +785,6 @@ const char* NzLuaInstance::ToString(int index, std::size_t* length) const
return lua_tolstring(m_state, index, length); return lua_tolstring(m_state, index, length);
} }
unsigned int NzLuaInstance::ToUnsigned(int index, bool* succeeded) const
{
int success;
unsigned int result = lua_tounsignedx(m_state, index, &success);
if (succeeded)
*succeeded = (success == 1);
return result;
}
void* NzLuaInstance::ToUserdata(int index) const void* NzLuaInstance::ToUserdata(int index) const
{ {
return lua_touserdata(m_state, index); return lua_touserdata(m_state, index);

View File

@ -92,7 +92,7 @@ NzUberShaderInstance* NzUberShaderPreprocessor::Get(const NzParameterList& param
// On construit l'instant // On construit l'instant
shaderIt = m_cache.emplace(flags, shader.Get()).first; shaderIt = m_cache.emplace(flags, shader.Get()).first;
} }
catch (const std::exception& e) catch (const std::exception&)
{ {
NzErrorFlags errFlags(nzErrorFlag_ThrowExceptionDisabled); NzErrorFlags errFlags(nzErrorFlag_ThrowExceptionDisabled);

View File

@ -253,9 +253,9 @@ bool NzFont::Precache(unsigned int characterSize, nzUInt32 style, char32_t chara
bool NzFont::Precache(unsigned int characterSize, nzUInt32 style, const NzString& characterSet) const bool NzFont::Precache(unsigned int characterSize, nzUInt32 style, const NzString& characterSet) const
{ {
unsigned int size; ///TODO: Itération UTF-8 => UTF-32 sans allocation de buffer (Exposer utf8cpp ?)
std::unique_ptr<char32_t[]> characters(characterSet.GetUtf32Buffer(&size)); std::u32string set = characterSet.GetUtf32String();
if (!characters) if (set.empty())
{ {
NazaraError("Invalid character set"); NazaraError("Invalid character set");
return false; return false;
@ -263,8 +263,8 @@ bool NzFont::Precache(unsigned int characterSize, nzUInt32 style, const NzString
nzUInt64 key = ComputeKey(characterSize, style); nzUInt64 key = ComputeKey(characterSize, style);
auto& glyphMap = m_glyphes[key]; auto& glyphMap = m_glyphes[key];
for (unsigned int i = 0; i < size; ++i) for (char32_t character : set)
PrecacheGlyph(glyphMap, characterSize, style, characters[i]); PrecacheGlyph(glyphMap, characterSize, style, character);
return true; return true;
} }

View File

@ -212,12 +212,12 @@ namespace
bool HasKerning() const override bool HasKerning() const override
{ {
return FT_HAS_KERNING(m_face); return FT_HAS_KERNING(m_face) != 0;
} }
bool IsScalable() const override bool IsScalable() const override
{ {
return FT_IS_SCALABLE(m_face); return FT_IS_SCALABLE(m_face) != 0;
} }
bool Open() bool Open()

View File

@ -220,11 +220,12 @@ namespace
vertexMapper.Unmap(); vertexMapper.Unmap();
subMesh->GenerateAABB();
subMesh->GenerateTangents();
subMesh->SetIndexBuffer(indexBuffer); subMesh->SetIndexBuffer(indexBuffer);
subMesh->SetMaterialIndex(0); subMesh->SetMaterialIndex(0);
subMesh->GenerateAABB();
subMesh->GenerateTangents();
mesh->AddSubMesh(subMesh); mesh->AddSubMesh(subMesh);
if (parameters.center) if (parameters.center)

View File

@ -41,7 +41,12 @@ m_transformMatrixUpdated(false)
NzNode::~NzNode() NzNode::~NzNode()
{ {
for (NzNode* child : m_childs) for (NzNode* child : m_childs)
child->SetParent(nullptr); {
// child->SetParent(nullptr); serait problématique car elle nous appellerait
child->m_parent = nullptr;
child->InvalidateNode();
child->OnParenting(nullptr);
}
SetParent(nullptr); SetParent(nullptr);
} }

View File

@ -192,9 +192,8 @@ void NzSimpleTextDrawer::UpdateGlyphs() const
return; return;
///TODO: Itération UTF-8 => UTF-32 sans allocation de buffer (Exposer utf8cpp ?) ///TODO: Itération UTF-8 => UTF-32 sans allocation de buffer (Exposer utf8cpp ?)
unsigned int size; std::u32string characters = m_text.GetUtf32String();
std::unique_ptr<char32_t[]> characters(m_text.GetUtf32Buffer(&size)); if (characters.empty())
if (!characters)
{ {
NazaraError("Invalid character set"); NazaraError("Invalid character set");
return; return;
@ -208,12 +207,11 @@ void NzSimpleTextDrawer::UpdateGlyphs() const
// On calcule les bornes en flottants pour accélérer les calculs (il est coûteux de changer de type trop souvent) // On calcule les bornes en flottants pour accélérer les calculs (il est coûteux de changer de type trop souvent)
bool firstGlyph = true; bool firstGlyph = true;
NzRectf textBounds = NzRectf::Zero(); NzRectf textBounds = NzRectf::Zero();
m_glyphs.reserve(size);
nzUInt32 previousCharacter = 0; nzUInt32 previousCharacter = 0;
for (unsigned int i = 0; i < size; ++i)
{
char32_t character = characters[i];
m_glyphs.reserve(characters.size());
for (char32_t character : characters)
{
if (previousCharacter != 0) if (previousCharacter != 0)
drawPos.x += m_font->GetKerning(m_characterSize, previousCharacter, character); drawPos.x += m_font->GetKerning(m_characterSize, previousCharacter, character);
@ -291,12 +289,12 @@ void NzSimpleTextDrawer::UpdateGlyphs() const
firstGlyph = false; firstGlyph = false;
} }
for (unsigned int j = 0; j < 4; ++j) for (unsigned int i = 0; i < 4; ++i)
textBounds.ExtendTo(glyph.corners[j]); textBounds.ExtendTo(glyph.corners[i]);
drawPos.x += advance; drawPos.x += advance;
m_glyphs.push_back(glyph); m_glyphs.push_back(glyph);
} }
m_bounds.Set(std::floor(textBounds.x), std::floor(textBounds.y), std::ceil(textBounds.width), std::ceil(textBounds.height)); m_bounds.Set(NzRectf(std::floor(textBounds.x), std::floor(textBounds.y), std::ceil(textBounds.width), std::ceil(textBounds.height)));
} }

View File

@ -5,6 +5,7 @@
#include <Nazara/Utility/Win32/CursorImpl.hpp> #include <Nazara/Utility/Win32/CursorImpl.hpp>
#include <Nazara/Core/Error.hpp> #include <Nazara/Core/Error.hpp>
#include <Nazara/Utility/Image.hpp> #include <Nazara/Utility/Image.hpp>
#include <Nazara/Utility/PixelFormat.hpp>
#include <Nazara/Utility/Debug.hpp> #include <Nazara/Utility/Debug.hpp>
bool NzCursorImpl::Create(const NzImage& cursor, int hotSpotX, int hotSpotY) bool NzCursorImpl::Create(const NzImage& cursor, int hotSpotX, int hotSpotY)

View File

@ -4,6 +4,7 @@
#include <Nazara/Utility/Win32/IconImpl.hpp> #include <Nazara/Utility/Win32/IconImpl.hpp>
#include <Nazara/Utility/Image.hpp> #include <Nazara/Utility/Image.hpp>
#include <Nazara/Utility/PixelFormat.hpp>
#include <Nazara/Utility/Debug.hpp> #include <Nazara/Utility/Debug.hpp>
bool NzIconImpl::Create(const NzImage& icon) bool NzIconImpl::Create(const NzImage& icon)

View File

@ -27,7 +27,7 @@
#define GWL_USERDATA GWLP_USERDATA #define GWL_USERDATA GWLP_USERDATA
#endif #endif
// N'est pas définit avec MinGW // N'est pas défini avec MinGW
#ifndef MAPVK_VK_TO_VSC #ifndef MAPVK_VK_TO_VSC
#define MAPVK_VK_TO_VSC 0 #define MAPVK_VK_TO_VSC 0
#endif #endif
@ -145,8 +145,6 @@ bool NzWindowImpl::Create(const NzVideoMode& mode, const NzString& title, nzUInt
m_callback = 0; m_callback = 0;
std::unique_ptr<wchar_t[]> wtitle(title.GetWideBuffer());
#if NAZARA_UTILITY_THREADED_WINDOW #if NAZARA_UTILITY_THREADED_WINDOW
NzMutex mutex; NzMutex mutex;
NzConditionVariable condition; NzConditionVariable condition;
@ -154,15 +152,18 @@ bool NzWindowImpl::Create(const NzVideoMode& mode, const NzString& title, nzUInt
// On attend que la fenêtre soit créée // On attend que la fenêtre soit créée
mutex.Lock(); mutex.Lock();
m_thread = new NzThread(WindowThread, &m_handle, win32StyleEx, wtitle.get(), win32Style, x, y, width, height, this, &mutex, &condition); m_thread = NzThread(WindowThread, &m_handle, win32StyleEx, title.GetWideString().data(), win32Style, x, y, width, height, this, &mutex, &condition);
condition.Wait(&mutex); condition.Wait(&mutex);
mutex.Unlock(); mutex.Unlock();
#else #else
m_handle = CreateWindowExW(win32StyleEx, className, wtitle.get(), win32Style, x, y, width, height, nullptr, nullptr, GetModuleHandle(nullptr), this); m_handle = CreateWindowExW(win32StyleEx, className, title.GetWideString().data(), win32Style, x, y, width, height, nullptr, nullptr, GetModuleHandle(nullptr), this);
#endif #endif
if (!m_handle) if (!m_handle)
{
NazaraError("Failed to create window: " + NzError::GetLastSystemError());
return false; return false;
}
if (fullscreen) if (fullscreen)
{ {
@ -220,13 +221,12 @@ void NzWindowImpl::Destroy()
if (m_ownsWindow) if (m_ownsWindow)
{ {
#if NAZARA_UTILITY_THREADED_WINDOW #if NAZARA_UTILITY_THREADED_WINDOW
if (m_thread) if (m_thread.IsJoinable())
{ {
m_threadActive = false; m_threadActive = false;
PostMessageW(m_handle, WM_NULL, 0, 0); // Pour réveiller le thread PostMessageW(m_handle, WM_NULL, 0, 0); // Pour réveiller le thread
m_thread->Join(); m_thread.Join();
delete m_thread;
} }
#else #else
if (m_handle) if (m_handle)
@ -445,8 +445,7 @@ void NzWindowImpl::SetStayOnTop(bool stayOnTop)
void NzWindowImpl::SetTitle(const NzString& title) void NzWindowImpl::SetTitle(const NzString& title)
{ {
std::unique_ptr<wchar_t[]> wTitle(title.GetWideBuffer()); SetWindowTextW(m_handle, title.GetWideString().data());
SetWindowTextW(m_handle, wTitle.get());
} }
void NzWindowImpl::SetVisible(bool visible) void NzWindowImpl::SetVisible(bool visible)
@ -1192,6 +1191,6 @@ void NzWindowImpl::WindowThread(HWND* handle, DWORD styleEx, const wchar_t* titl
while (window->m_threadActive) while (window->m_threadActive)
window->ProcessEvents(true); window->ProcessEvents(true);
DestroyWindow(*handle); DestroyWindow(winHandle);
} }
#endif #endif

View File

@ -11,6 +11,7 @@
#include <Nazara/Core/NonCopyable.hpp> #include <Nazara/Core/NonCopyable.hpp>
#include <Nazara/Core/String.hpp> #include <Nazara/Core/String.hpp>
#include <Nazara/Core/Thread.hpp>
#include <Nazara/Math/Vector2.hpp> #include <Nazara/Math/Vector2.hpp>
#include <Nazara/Utility/Config.hpp> #include <Nazara/Utility/Config.hpp>
#include <Nazara/Utility/Keyboard.hpp> #include <Nazara/Utility/Keyboard.hpp>
@ -22,7 +23,6 @@
#if NAZARA_UTILITY_THREADED_WINDOW #if NAZARA_UTILITY_THREADED_WINDOW
class NzConditionVariable; class NzConditionVariable;
class NzMutex; class NzMutex;
class NzThread;
#endif #endif
class NzWindow; class NzWindow;
@ -95,7 +95,7 @@ class NzWindowImpl : NzNonCopyable
NzVector2i m_position; NzVector2i m_position;
NzVector2ui m_size; NzVector2ui m_size;
#if NAZARA_UTILITY_THREADED_WINDOW #if NAZARA_UTILITY_THREADED_WINDOW
NzThread* m_thread; NzThread m_thread;
#endif #endif
NzWindow* m_parent; NzWindow* m_parent;
bool m_eventListener; bool m_eventListener;