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
*.project
# Visual Studio
*.filters
*.vcxproj
*.tlog
*.sln
*.vcxprojResolveAssemblyReference.cache
*.exp
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Compiled Dynamic libraries
*.so
*.lib
# Compiled Static libraries
*.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>
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
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;

View File

@ -10,7 +10,7 @@
/// Ce fichier sert à vérifier la valeur des constantes du fichier Config.hpp
#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
#if defined(NAZARA_DEBUG) && !NAZARA_AUDIO_MANAGE_MEMORY
@ -18,6 +18,8 @@
#define NAZARA_AUDIO_MANAGE_MEMORY 1
#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

View File

@ -4,13 +4,16 @@
#pragma once
#ifndef NAZARA_TUPLE_HPP
#define NAZARA_TUPLE_HPP
#ifndef NAZARA_ALGORITHM_CORE_HPP
#define NAZARA_ALGORITHM_CORE_HPP
#include <Nazara/Prerequesites.hpp>
#include <functional>
#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);
#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>
///TODO: Améliorer l'implémentation de UnpackTuple
template<unsigned int N>
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>
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))
h = 0; // hue must be < 1
int i = h;
int i = static_cast<unsigned int>(h);
float v1 = value * (1.f - s);
float v2 = value * (1.f - s * (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
#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
#if defined(NAZARA_DEBUG) && !NAZARA_CORE_MANAGE_MEMORY
@ -18,8 +18,10 @@
#define NAZARA_CORE_MANAGE_MEMORY 1
#endif
CheckTypeAndVal(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");
CheckTypeAndVal(NAZARA_CORE_WINDOWS_CS_SPINLOCKS, integral, >=, 0, " shall be a positive integer");
NazaraCheckTypeAndVal(NAZARA_CORE_DECIMAL_DIGITS, integral, >, 0, " shall be a strictly positive integer");
NazaraCheckTypeAndVal(NAZARA_CORE_FILE_BUFFERSIZE, integral, >, 0, " shall be a strictly positive integer");
NazaraCheckTypeAndVal(NAZARA_CORE_WINDOWS_CS_SPINLOCKS, integral, >=, 0, " shall be a positive integer");
#undef NazaraCheckTypeAndVal
#endif // NAZARA_CONFIG_CHECK_CORE_HPP

View File

@ -15,7 +15,8 @@
#if defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || (defined(__MIPS__) && defined(__MISPEB__)) || \
defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC) || defined(__sparc__) || defined(__hppa__)
#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
#else
#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
#define NAZARA_FUNCTOR_HPP
#include <Nazara/Core/Tuple.hpp>
#include <Nazara/Core/Algorithm.hpp>
// Inspiré du code de la SFML par Laurent Gomila

View File

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

View File

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

View File

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

View File

@ -87,10 +87,10 @@ class NAZARA_API NzString : public NzHashable
const char* GetConstBuffer() const;
unsigned int GetLength() const;
unsigned int GetSize() const;
char* GetUtf8Buffer(unsigned int* size = nullptr) const;
char16_t* GetUtf16Buffer(unsigned int* size = nullptr) const;
char32_t* GetUtf32Buffer(unsigned int* size = nullptr) const;
wchar_t* GetWideBuffer(unsigned int* size = nullptr) const;
std::string GetUtf8String() const;
std::u16string GetUtf16String() const;
std::u32string GetUtf32String() const;
std::wstring GetWideString() const;
NzString GetWord(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/Core/Functor.hpp>
#include <Nazara/Core/NonCopyable.hpp>
#include <ostream>
#include <iosfwd>
class NzThreadImpl;

View File

@ -10,7 +10,7 @@
/// Ce fichier sert à vérifier la valeur des constantes du fichier Config.hpp
#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
#if defined(NAZARA_DEBUG) && !NAZARA_GRAPHICS_MANAGE_MEMORY
@ -18,7 +18,9 @@
#define NAZARA_GRAPHICS_MANAGE_MEMORY 1
#endif
CheckTypeAndVal(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_INSTANCING_MIN_INSTANCES_COUNT, 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

View File

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

View File

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

View File

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

View File

@ -23,7 +23,7 @@ class NAZARA_API NzSceneNode : public NzNode
public:
NzSceneNode();
NzSceneNode(const NzSceneNode& sceneNode);
NzSceneNode(NzSceneNode& sceneNode) = delete;
NzSceneNode(NzSceneNode&& sceneNode) = delete;
virtual ~NzSceneNode();
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 GetGlobalRight() const;
NzVector3f GetGlobalUp() const;
const NzMatrix4f& GetInvViewProjMatrix() const;
const NzMatrix4f& GetProjectionMatrix() const;
const NzVector2f& GetSize() const;
const NzRenderTarget* GetTarget() const;
const NzRectf& GetTargetRegion() const;
const NzMatrix4f& GetViewMatrix() const;
const NzMatrix4f& GetViewProjMatrix() const;
const NzRecti& GetViewport() const;
float GetZFar() const;
float GetZNear() const;
NzVector2i MapWorldToPixel(const NzVector2f& coords);
NzVector2f MapPixelToWorld(const NzVector2i& pixel);
void SetSize(const NzVector2f& size);
void SetSize(float width, float height);
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;
void UpdateFrustum() const;
void UpdateInvViewProjMatrix() const;
void UpdateProjectionMatrix() const;
void UpdateViewMatrix() const;
void UpdateViewProjMatrix() const;
void UpdateViewport() const;
mutable NzFrustumf m_frustum;
mutable NzMatrix4f m_invViewProjMatrix;
mutable NzMatrix4f m_projectionMatrix;
mutable NzMatrix4f m_viewMatrix;
mutable NzMatrix4f m_viewProjMatrix;
NzRectf m_targetRegion;
mutable NzRecti m_viewport;
NzVector2f m_size;
const NzRenderTarget* m_target;
mutable bool m_frustumUpdated;
mutable bool m_invViewProjMatrixUpdated;
mutable bool m_projectionMatrixUpdated;
mutable bool m_viewMatrixUpdated;
mutable bool m_viewProjMatrixUpdated;
mutable bool m_viewportUpdated;
float m_zFar;
float m_zNear;

View File

@ -38,8 +38,8 @@ class NAZARA_API NzLuaInstance : NzNonCopyable
void CheckAny(int index) const;
bool CheckBoolean(int index) const;
bool CheckBoolean(int index, bool defValue) const;
int CheckInteger(int index) const;
int CheckInteger(int index, int defValue) const;
long long CheckInteger(int index) const;
long long CheckInteger(int index, long long defValue) const;
double CheckNumber(int index) const;
double CheckNumber(int index, double defValue) 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, const char* defValue, std::size_t* length = nullptr) 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 NzString& tname) const;
@ -71,19 +69,19 @@ class NAZARA_API NzLuaInstance : NzNonCopyable
bool ExecuteFromStream(NzInputStream& stream);
int GetAbsIndex(int index) const;
void GetField(const char* fieldName, int index = -1) const;
void GetField(const NzString& fieldName, int index = -1) const;
void GetGlobal(const char* name) const;
void GetGlobal(const NzString& name) const;
nzLuaType GetField(const char* fieldName, int index = -1) const;
nzLuaType GetField(const NzString& fieldName, int index = -1) const;
nzLuaType GetGlobal(const char* name) const;
nzLuaType GetGlobal(const NzString& name) const;
lua_State* GetInternalState() const;
NzString GetLastError() const;
nzUInt32 GetMemoryLimit() const;
nzUInt32 GetMemoryUsage() const;
void GetMetatable(const char* tname) const;
void GetMetatable(const NzString& tname) const;
nzLuaType GetMetatable(const char* tname) const;
nzLuaType GetMetatable(const NzString& tname) const;
bool GetMetatable(int index) const;
unsigned int GetStackTop() const;
void GetTable(int index = -2) const;
nzLuaType GetTable(int index = -2) const;
nzUInt32 GetTimeLimit() const;
nzLuaType GetType(int index) const;
const char* GetTypeName(nzLuaType type) const;
@ -108,7 +106,7 @@ class NAZARA_API NzLuaInstance : NzNonCopyable
void PushBoolean(bool value);
void PushCFunction(NzLuaCFunction func, int upvalueCount = 0);
void PushFunction(NzLuaFunction func);
void PushInteger(int value);
void PushInteger(long long value);
void PushLightUserdata(void* value);
void PushMetatable(const char* str);
void PushMetatable(const NzString& str);
@ -118,7 +116,6 @@ class NAZARA_API NzLuaInstance : NzNonCopyable
void PushString(const char* str);
void PushString(const NzString& str);
void PushTable(unsigned int sequenceElementCount = 0, unsigned int arrayElementCount = 0);
void PushUnsigned(unsigned int value);
void* PushUserdata(unsigned int size);
void PushValue(int index);
@ -137,11 +134,10 @@ class NAZARA_API NzLuaInstance : NzNonCopyable
void SetTimeLimit(nzUInt32 timeLimit);
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;
const void* ToPointer(int index) 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 char* 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
{
str += symbols[number % radix];
str.Append(symbols[number % radix]);
number /= radix;
}
while (number > 0);
if (negative)
str += '-';
str.Append('-');
return str.Reversed();
return str.Reverse();
}
template<typename T>

View File

@ -143,7 +143,7 @@
// Détection 64 bits
#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
#endif

View File

@ -10,7 +10,7 @@
/// Ce fichier sert à vérifier la valeur des constantes du fichier Config.hpp
#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
#if defined(NAZARA_DEBUG) && !NAZARA_RENDERER_MANAGE_MEMORY
@ -18,6 +18,8 @@
#define NAZARA_RENDERER_MANAGE_MEMORY 1
#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

View File

@ -10,7 +10,7 @@
/// Ce fichier sert à vérifier la valeur des constantes du fichier Config.hpp
#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
#if defined(NAZARA_DEBUG) && !NAZARA_UTILITY_MANAGE_MEMORY
@ -18,6 +18,8 @@
#define NAZARA_UTILITY_MANAGE_MEMORY 1
#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

View File

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

View File

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

View File

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

View File

@ -17,7 +17,7 @@
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);
s_lastError = error;
@ -27,16 +27,17 @@ void NzError::Error(nzErrorType type, const NzString& error)
#if NAZARA_CORE_EXIT_ON_ASSERT_FAILURE
if (type == nzErrorType_AssertFailed)
std::exit(EXIT_FAILURE);
std::abort();
#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);
}
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);
s_lastError = error;
@ -44,13 +45,14 @@ void NzError::Error(nzErrorType type, const NzString& error, unsigned int line,
s_lastErrorFunction = function;
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 (type == nzErrorType_AssertFailed)
std::exit(EXIT_FAILURE);
std::abort();
#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()

View File

@ -733,7 +733,7 @@ bool NzFile::FillHash(NzAbstractHash* hash) const
unsigned int size;
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)
{
NazaraError("Unable to read file");

View File

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

View File

@ -4,6 +4,7 @@
#include <Nazara/Core/HardwareInfo.hpp>
#include <Nazara/Core/Error.hpp>
#include <algorithm>
#include <cstdlib>
#include <cstring>
@ -77,7 +78,11 @@ namespace
bool s_initialized = false;
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()
@ -137,67 +142,86 @@ bool NzHardwareInfo::Initialize()
s_initialized = true;
nzUInt32 result[4];
nzUInt32 registers[4]; // Récupère les quatre registres (EAX, EBX, ECX et EDX)
NzHardwareInfoImpl::Cpuid(0, result);
std::memcpy(&s_vendor[0], &result[1], 4);
std::memcpy(&s_vendor[4], &result[3], 4);
std::memcpy(&s_vendor[8], &result[2], 4);
// Pour plus de clarté
nzUInt32& eax = registers[0];
nzUInt32& ebx = registers[1];
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
s_vendorEnum = nzProcessorVendor_Unknown;
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;
break;
}
}
unsigned int ids = result[0];
if (ids >= 1)
if (eax >= 1)
{
NzHardwareInfoImpl::Cpuid(1, result);
s_capabilities[nzProcessorCap_AVX] = (result[2] & (1U << 28)) != 0;
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;
// Récupération de certaines capacités du processeur (ECX et EDX, fonction 1)
NzHardwareInfoImpl::Cpuid(1, 0, registers);
NzHardwareInfoImpl::Cpuid(0x80000000, result);
unsigned int exIds = result[0];
s_capabilities[nzProcessorCap_AVX] = (ecx & (1U << 28)) != 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);
s_capabilities[nzProcessorCap_x64] = (result[3] & (1U << 29)) != 0;
s_capabilities[nzProcessorCap_FMA4] = (result[2] & (1U << 16)) != 0;
s_capabilities[nzProcessorCap_SSE4a] = (result[2] & (1U << 6)) != 0;
s_capabilities[nzProcessorCap_XOP] = (result[2] & (1U << 11)) != 0;
if (exIds >= 0x80000004)
// Récupération d'une chaîne de caractère décrivant le processeur (EAX, EBX, ECX et EDX,
// fonctions de 0x80000002 à 0x80000004 compris)
char* ptr = &s_brandString[0];
for (nzUInt32 code = 0x80000002; code <= 0x80000004; ++code)
{
char* ptr = &s_brandString[0];
for (nzUInt32 code = 0x80000002; code <= 0x80000004; ++code)
{
NzHardwareInfoImpl::Cpuid(code, result);
std::memcpy(ptr, &result[0], 16);
NzHardwareInfoImpl::Cpuid(code, 0, registers);
std::memcpy(ptr, &registers[0], 4*sizeof(nzUInt32)); // On rajoute les 16 octets à la chaîne
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;
}
bool NzHardwareInfo::IsCpuidSupported()
{
return NzHardwareInfoImpl::IsCpuidSupported();
}
bool NzHardwareInfo::IsInitialized()
{
return s_initialized;

View File

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

View File

@ -91,7 +91,7 @@ bool NzParameterList::GetFloatParameter(const NzString& name, float* value) cons
return true;
case nzParameterType_Integer:
*value = it->second.value.intVal;
*value = static_cast<float>(it->second.value.intVal);
return true;
case nzParameterType_String:
@ -99,7 +99,7 @@ bool NzParameterList::GetFloatParameter(const NzString& name, float* value) cons
double converted;
if (it->second.value.stringVal.ToDouble(&converted))
{
*value = converted;
*value = static_cast<float>(converted);
return true;
}
@ -133,7 +133,7 @@ bool NzParameterList::GetIntegerParameter(const NzString& name, int* value) cons
return true;
case nzParameterType_Float:
*value = it->second.value.floatVal;
*value = static_cast<int>(it->second.value.floatVal);
return true;
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())
{
*value = converted;
*value = static_cast<int>(converted);
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"
// 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;
}
char* NzString::GetUtf8Buffer(unsigned int* size) const
std::string NzString::GetUtf8String() const
{
if (m_sharedString->size == 0)
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;
return std::string(m_sharedString->string, m_sharedString->size);
}
char16_t* NzString::GetUtf16Buffer(unsigned int* size) const
std::u16string NzString::GetUtf16String() const
{
if (m_sharedString->size == 0)
return nullptr;
return std::u16string();
std::vector<char16_t> utf16;
utf16.reserve(m_sharedString->size);
std::u16string str;
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();
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;
return str;
}
char32_t* NzString::GetUtf32Buffer(unsigned int* size) const
std::u32string NzString::GetUtf32String() const
{
if (m_sharedString->size == 0)
return nullptr;
return std::u32string();
unsigned int bufferSize = utf8::distance(m_sharedString->string, &m_sharedString->string[m_sharedString->size]);
if (bufferSize == 0)
return nullptr;
std::u32string str;
str.reserve(m_sharedString->size);
char32_t* buffer = new char32_t[bufferSize+1];
utf8::utf8to32(m_sharedString->string, &m_sharedString->string[m_sharedString->size], buffer);
buffer[bufferSize] ='\0';
utf8::utf8to32(begin(), end(), std::back_inserter(str));
if (size)
*size = bufferSize;
return buffer;
return str;
}
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");
if (m_sharedString->size == 0)
return nullptr;
return std::wstring();
unsigned int bufferSize = utf8::distance(m_sharedString->string, &m_sharedString->string[m_sharedString->size]);
if (bufferSize == 0)
return nullptr;
std::wstring str;
str.reserve(m_sharedString->size);
wchar_t* buffer = new wchar_t[bufferSize+1];
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
{
wchar_t* ptr = buffer;
utf8::unchecked::iterator<const char*> it(m_sharedString->string);
do
{
char32_t cp = *it;
if (cp <= 0xFFFF && (cp < 0xD800 || cp > 0xDFFF)) // @Laurent Gomila
*ptr++ = static_cast<wchar_t>(cp);
str.push_back(static_cast<wchar_t>(cp));
else
*ptr++ = L'?';
str.push_back(L'?');
}
while (*it++);
}
if (size)
*size = bufferSize;
return buffer;
return str;
}
NzString NzString::GetWord(unsigned int index, nzUInt32 flags) const
@ -3162,7 +3129,7 @@ NzString NzString::SubStringFrom(char character, int startPos, bool fromLast, bo
else
pos = Find(character, startPos, flags);
if (pos == 0 and include)
if (pos == 0 && include)
return *this;
else if (pos == npos)
return NzString();

View File

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

View File

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

View File

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

View File

@ -12,15 +12,18 @@
#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)
__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)
// Source: http://stackoverflow.com/questions/1666093/cpuid-implementations-in-c
asm volatile ("cpuid" // Besoin d'être volatile ?
: "=a" (result[0]), "=b" (result[1]), "=c" (result[2]), "=d" (result[3]) // output
: "a" (code), "c" (0)); // input
: "=a" (registers[0]), "=b" (registers[1]), "=c" (registers[2]), "=d" (registers[3]) // output
: "a" (functionId), "c" (subFunctionId)); // input
#else
NazaraInternalError("Cpuid has been called although it is not supported");
#endif
@ -37,10 +40,10 @@ unsigned int NzHardwareInfoImpl::GetProcessorCount()
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
#else
#else
#if defined(NAZARA_COMPILER_MSVC)
int supported;
__asm
{
@ -59,31 +62,27 @@ bool NzHardwareInfoImpl::IsCpuidSupported()
};
return supported != 0;
#endif // NAZARA_PLATFORM_x64
#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
#elif defined(NAZARA_COMPILER_CLANG) || defined(NAZARA_COMPILER_GCC) || defined(NAZARA_COMPILER_INTEL)
int supported;
asm volatile (" pushfl\n"
" pop %%eax\n"
" mov %%eax, %%ecx\n"
" xor $0x200000, %%eax\n"
" push %%eax\n"
" popfl\n"
" pushfl\n"
" pop %%eax\n"
" xor %%ecx, %%eax\n"
" mov %%eax, %0\n"
" push %%ecx\n"
" popfl"
: "=m" (supported) // output
: // input
: "eax", "ecx", "memory"); // clobbered register
asm volatile (" pushfl\n"
" pop %%eax\n"
" mov %%eax, %%ecx\n"
" xor $0x200000, %%eax\n"
" push %%eax\n"
" popfl\n"
" pushfl\n"
" pop %%eax\n"
" xor %%ecx, %%eax\n"
" mov %%eax, %0\n"
" push %%ecx\n"
" popfl"
: "=m" (supported) // output
: // input
: "eax", "ecx", "memory"); // clobbered register
return supported != 0;
#endif // NAZARA_PLATFORM_x64
#else
#else
return false;
#endif
#endif
}

View File

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

View File

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

View File

@ -3,6 +3,8 @@
// For conditions of distribution and use, see copyright notice in Config.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/Model.hpp>
#include <Nazara/Graphics/Loaders/OBJ/MTLParser.hpp>
@ -16,6 +18,8 @@
#include <unordered_map>
#include <Nazara/Graphics/Debug.hpp>
///TODO: N'avoir qu'un seul VertexBuffer communs à tous les meshes
namespace
{
bool IsSupported(const NzString& extension)
@ -31,10 +35,97 @@ namespace
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)
{
NzOBJParser parser(stream);
if (!parser.Parse())
{
NazaraError("OBJ parser failed");
@ -53,10 +144,15 @@ namespace
const NzVector3f* normals = parser.GetNormals();
const NzVector3f* texCoords = parser.GetTexCoords();
std::vector<unsigned int> faceIndices;
const NzOBJParser::Mesh* meshes = parser.GetMeshes();
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)
{
unsigned int faceCount = meshes[i].faces.size();
@ -66,8 +162,35 @@ namespace
std::vector<unsigned int> indices;
indices.reserve(faceCount*3); // Pire cas si les faces sont des triangles
// Bien plus rapide qu'un vector (pour la recherche)
std::unordered_map<int, std::unordered_map<int, std::unordered_map<int, unsigned int>>> vertices;
// Afin d'utiliser OBJParser::FaceVertex comme clé dans un unordered_map,
// 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;
for (unsigned int j = 0; j < faceCount; ++j)
@ -79,15 +202,11 @@ namespace
{
const NzOBJParser::FaceVertex& vertex = meshes[i].faces[j].vertices[k];
auto& map = vertices[vertex.texCoord][vertex.normal];
auto it = map.find(vertex.position);
if (it == map.end())
{
faceIndices[k] = vertexCount;
map[vertex.position] = vertexCount++;
}
else
faceIndices[k] = it->second;
auto it = vertices.find(vertex);
if (it == vertices.end())
it = vertices.emplace(vertex, vertexCount++).first;
faceIndices[k] = it->second;
}
for (unsigned int k = 1; k < faceVertexCount-1; ++k)
@ -114,36 +233,29 @@ namespace
bool hasTexCoords = true;
NzBufferMapper<NzVertexBuffer> vertexMapper(vertexBuffer, nzBufferAccess_WriteOnly);
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)
{
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;
}
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é
}
else
hasTexCoords = false;
}
vertexMapper.Unmap();
@ -184,90 +296,8 @@ namespace
NzString mtlLib = parser.GetMtlLib();
if (parameters.loadMaterials && !mtlLib.IsEmpty())
{
NzFile file(stream.GetDirectory() + mtlLib);
if (file.Open(NzFile::ReadOnly | NzFile::Text))
{
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() + ')');
NzErrorFlags flags(nzErrorFlag_ThrowExceptionDisabled);
LoadMaterials(model, stream.GetDirectory() + mtlLib, parameters.material, materials, meshes, meshCount);
}
return true;

View File

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

View File

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

View File

@ -81,12 +81,12 @@ void NzScene::Draw()
if (m_renderTechniqueRanking > 0)
{
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
{
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;

View File

@ -44,7 +44,8 @@ m_nextFrame(model.m_nextFrame)
NzSkeletalModel::~NzSkeletalModel()
{
m_scene->UnregisterForUpdate(this);
if (m_scene)
m_scene->UnregisterForUpdate(this);
}
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* 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);
if (it != m_renderInfos.end())
{
@ -343,7 +344,7 @@ bool NzTextSprite::OnAtlasLayerChange(const NzAbstractAtlas* atlas, NzAbstractIm
NzVector2ui newSize(newTexture->GetSize());
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));
for (unsigned int i = 0; i < indices.count; ++i)
{
@ -372,7 +373,7 @@ void NzTextSprite::OnAtlasReleased(const NzAbstractAtlas* atlas, void* userdata)
#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
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();
}

View File

@ -13,8 +13,10 @@ m_targetRegion(0.f, 0.f, 1.f, 1.f),
m_size(0.f),
m_target(nullptr),
m_frustumUpdated(false),
m_invViewProjMatrixUpdated(false),
m_projectionMatrixUpdated(false),
m_viewMatrixUpdated(false),
m_viewProjMatrixUpdated(false),
m_viewportUpdated(false),
m_zFar(1.f),
m_zNear(-1.f)
@ -95,6 +97,14 @@ NzVector3f NzView::GetGlobalUp() const
return -NzVector3f::UnitY();
}
const NzMatrix4f& NzView::GetInvViewProjMatrix() const
{
if (!m_invViewProjMatrixUpdated)
UpdateInvViewProjMatrix();
return m_invViewProjMatrix;
}
const NzMatrix4f& NzView::GetProjectionMatrix() const
{
if (!m_projectionMatrixUpdated)
@ -121,6 +131,14 @@ const NzMatrix4f& NzView::GetViewMatrix() const
return m_viewMatrix;
}
const NzMatrix4f& NzView::GetViewProjMatrix() const
{
if (!m_viewProjMatrixUpdated)
UpdateViewProjMatrix();
return m_viewProjMatrix;
}
const NzRecti& NzView::GetViewport() const
{
#if NAZARA_GRAPHICS_SAFE
@ -147,6 +165,44 @@ float NzView::GetZNear() const
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)
{
SetSize(size.x, size.y);
@ -178,7 +234,9 @@ void NzView::SetTargetRegion(const NzRectf& region)
m_targetRegion = region;
m_frustumUpdated = false;
m_invViewProjMatrixUpdated = false;
m_projectionMatrixUpdated = false;
m_viewProjMatrixUpdated = false;
m_viewportUpdated = false;
}
@ -204,7 +262,9 @@ void NzView::SetZFar(float zFar)
m_zFar = zFar;
m_frustumUpdated = false;
m_invViewProjMatrixUpdated = false;
m_projectionMatrixUpdated = false;
m_viewProjMatrixUpdated = false;
}
void NzView::SetZNear(float zNear)
@ -212,7 +272,9 @@ void NzView::SetZNear(float zNear)
m_zNear = zNear;
m_frustumUpdated = false;
m_invViewProjMatrixUpdated = false;
m_projectionMatrixUpdated = false;
m_viewProjMatrixUpdated = false;
}
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
m_frustumUpdated = false;
m_invViewProjMatrixUpdated = false;
m_viewMatrixUpdated = false;
m_viewProjMatrixUpdated = false;
}
void NzView::OnRenderTargetReleased(const NzRenderTarget* renderTarget, void* userdata)
@ -287,6 +351,15 @@ void NzView::UpdateFrustum() const
m_frustumUpdated = true;
}
void NzView::UpdateInvViewProjMatrix() const
{
if (!m_viewProjMatrixUpdated)
UpdateViewProjMatrix();
m_viewProjMatrix.GetInverseAffine(&m_invViewProjMatrix);
m_invViewProjMatrixUpdated = true;
}
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
@ -294,7 +367,7 @@ void NzView::UpdateProjectionMatrix() const
if (!m_viewportUpdated)
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
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;
}
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
{
unsigned int width = m_target->GetWidth();

View File

@ -19,6 +19,45 @@
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
{
NzInputStream* stream;
@ -134,7 +173,7 @@ bool NzLuaInstance::CheckBoolean(int index) const
return false;
}
return lua_toboolean(m_state, index);
return lua_toboolean(m_state, index) != 0;
}
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))
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
@ -198,16 +237,6 @@ void NzLuaInstance::CheckType(int index, nzLuaType type) const
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
{
return luaL_checkudata(m_state, index, tname);
@ -228,7 +257,7 @@ bool NzLuaInstance::Compare(int index1, int index2, nzLuaComparison comparison)
}
#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)
@ -395,24 +424,24 @@ int NzLuaInstance::GetAbsIndex(int index) const
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
@ -435,19 +464,19 @@ nzUInt32 NzLuaInstance::GetMemoryUsage() const
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
{
return lua_getmetatable(m_state, index) == 1;
return lua_getmetatable(m_state, index) != 0;
}
unsigned int NzLuaInstance::GetStackTop() const
@ -455,9 +484,9 @@ unsigned int NzLuaInstance::GetStackTop() const
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
@ -467,41 +496,7 @@ nzUInt32 NzLuaInstance::GetTimeLimit() const
nzLuaType NzLuaInstance::GetType(int index) const
{
switch (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;
}
return FromLuaType(lua_type(m_state, index));
}
const char* NzLuaInstance::GetTypeName(nzLuaType type) const
@ -527,34 +522,34 @@ bool NzLuaInstance::IsOfType(int index, nzLuaType type) const
switch (type)
{
case nzLuaType_Boolean:
return lua_isboolean(m_state, index) == 1;
return lua_isboolean(m_state, index) != 0;
case nzLuaType_Function:
return lua_isfunction(m_state, index) == 1;
return lua_isfunction(m_state, index) != 0;
case nzLuaType_LightUserdata:
return lua_islightuserdata(m_state, index) == 1;
return lua_islightuserdata(m_state, index) != 0;
case nzLuaType_Nil:
return lua_isnil(m_state, index) == 1;
return lua_isnil(m_state, index) != 0;
case nzLuaType_None:
return lua_isnone(m_state, index) == 1;
return lua_isnone(m_state, index) != 0;
case nzLuaType_Number:
return lua_isnumber(m_state, index) == 1;
return lua_isnumber(m_state, index) != 0;
case nzLuaType_String:
return lua_isstring(m_state, index) == 1;
return lua_isstring(m_state, index) != 0;
case nzLuaType_Table:
return lua_istable(m_state, index) == 1;
return lua_istable(m_state, index) != 0;
case nzLuaType_Thread:
return lua_isthread(m_state, index) == 1;
return lua_isthread(m_state, index) != 0;
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) + ')');
@ -574,7 +569,7 @@ bool NzLuaInstance::IsOfType(int index, const NzString& tname) 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
@ -589,17 +584,17 @@ void NzLuaInstance::MoveTo(NzLuaInstance* instance, int n)
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)
{
return luaL_newmetatable(m_state, str.GetConstBuffer());
return luaL_newmetatable(m_state, str.GetConstBuffer()) != 0;
}
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)
@ -609,7 +604,7 @@ void NzLuaInstance::Pop(unsigned int n)
void NzLuaInstance::PushBoolean(bool value)
{
lua_pushboolean(m_state, value);
lua_pushboolean(m_state, (value) ? 1 : 0);
}
void NzLuaInstance::PushCFunction(NzLuaCFunction func, int upvalueCount)
@ -625,7 +620,7 @@ void NzLuaInstance::PushFunction(NzLuaFunction func)
lua_pushcclosure(m_state, ProxyFunc, 1);
}
void NzLuaInstance::PushInteger(int value)
void NzLuaInstance::PushInteger(long long 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);
}
void NzLuaInstance::PushUnsigned(unsigned int value)
{
lua_pushunsigned(m_state, value);
}
void* NzLuaInstance::PushUserdata(unsigned int size)
{
return lua_newuserdata(m_state, size);
@ -760,16 +750,16 @@ void NzLuaInstance::SetTimeLimit(nzUInt32 timeLimit)
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 result = lua_tointegerx(m_state, index, &success);
long long result = lua_tointegerx(m_state, index, &success);
if (succeeded)
*succeeded = (success == 1);
*succeeded = (success != 0);
return result;
}
@ -780,7 +770,7 @@ double NzLuaInstance::ToNumber(int index, bool* succeeded) const
double result = lua_tonumberx(m_state, index, &success);
if (succeeded)
*succeeded = (success == 1);
*succeeded = (success != 0);
return result;
}
@ -795,17 +785,6 @@ const char* NzLuaInstance::ToString(int index, std::size_t* length) const
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
{
return lua_touserdata(m_state, index);

View File

@ -92,7 +92,7 @@ NzUberShaderInstance* NzUberShaderPreprocessor::Get(const NzParameterList& param
// On construit l'instant
shaderIt = m_cache.emplace(flags, shader.Get()).first;
}
catch (const std::exception& e)
catch (const std::exception&)
{
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
{
unsigned int size;
std::unique_ptr<char32_t[]> characters(characterSet.GetUtf32Buffer(&size));
if (!characters)
///TODO: Itération UTF-8 => UTF-32 sans allocation de buffer (Exposer utf8cpp ?)
std::u32string set = characterSet.GetUtf32String();
if (set.empty())
{
NazaraError("Invalid character set");
return false;
@ -263,8 +263,8 @@ bool NzFont::Precache(unsigned int characterSize, nzUInt32 style, const NzString
nzUInt64 key = ComputeKey(characterSize, style);
auto& glyphMap = m_glyphes[key];
for (unsigned int i = 0; i < size; ++i)
PrecacheGlyph(glyphMap, characterSize, style, characters[i]);
for (char32_t character : set)
PrecacheGlyph(glyphMap, characterSize, style, character);
return true;
}

View File

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

View File

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

View File

@ -41,7 +41,12 @@ m_transformMatrixUpdated(false)
NzNode::~NzNode()
{
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);
}

View File

@ -192,9 +192,8 @@ void NzSimpleTextDrawer::UpdateGlyphs() const
return;
///TODO: Itération UTF-8 => UTF-32 sans allocation de buffer (Exposer utf8cpp ?)
unsigned int size;
std::unique_ptr<char32_t[]> characters(m_text.GetUtf32Buffer(&size));
if (!characters)
std::u32string characters = m_text.GetUtf32String();
if (characters.empty())
{
NazaraError("Invalid character set");
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)
bool firstGlyph = true;
NzRectf textBounds = NzRectf::Zero();
m_glyphs.reserve(size);
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)
drawPos.x += m_font->GetKerning(m_characterSize, previousCharacter, character);
@ -291,12 +289,12 @@ void NzSimpleTextDrawer::UpdateGlyphs() const
firstGlyph = false;
}
for (unsigned int j = 0; j < 4; ++j)
textBounds.ExtendTo(glyph.corners[j]);
for (unsigned int i = 0; i < 4; ++i)
textBounds.ExtendTo(glyph.corners[i]);
drawPos.x += advance;
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/Core/Error.hpp>
#include <Nazara/Utility/Image.hpp>
#include <Nazara/Utility/PixelFormat.hpp>
#include <Nazara/Utility/Debug.hpp>
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/Image.hpp>
#include <Nazara/Utility/PixelFormat.hpp>
#include <Nazara/Utility/Debug.hpp>
bool NzIconImpl::Create(const NzImage& icon)

View File

@ -27,7 +27,7 @@
#define GWL_USERDATA GWLP_USERDATA
#endif
// N'est pas définit avec MinGW
// N'est pas défini avec MinGW
#ifndef MAPVK_VK_TO_VSC
#define MAPVK_VK_TO_VSC 0
#endif
@ -145,8 +145,6 @@ bool NzWindowImpl::Create(const NzVideoMode& mode, const NzString& title, nzUInt
m_callback = 0;
std::unique_ptr<wchar_t[]> wtitle(title.GetWideBuffer());
#if NAZARA_UTILITY_THREADED_WINDOW
NzMutex mutex;
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
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);
mutex.Unlock();
#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
if (!m_handle)
{
NazaraError("Failed to create window: " + NzError::GetLastSystemError());
return false;
}
if (fullscreen)
{
@ -220,13 +221,12 @@ void NzWindowImpl::Destroy()
if (m_ownsWindow)
{
#if NAZARA_UTILITY_THREADED_WINDOW
if (m_thread)
if (m_thread.IsJoinable())
{
m_threadActive = false;
PostMessageW(m_handle, WM_NULL, 0, 0); // Pour réveiller le thread
m_thread->Join();
delete m_thread;
m_thread.Join();
}
#else
if (m_handle)
@ -445,8 +445,7 @@ void NzWindowImpl::SetStayOnTop(bool stayOnTop)
void NzWindowImpl::SetTitle(const NzString& title)
{
std::unique_ptr<wchar_t[]> wTitle(title.GetWideBuffer());
SetWindowTextW(m_handle, wTitle.get());
SetWindowTextW(m_handle, title.GetWideString().data());
}
void NzWindowImpl::SetVisible(bool visible)
@ -1192,6 +1191,6 @@ void NzWindowImpl::WindowThread(HWND* handle, DWORD styleEx, const wchar_t* titl
while (window->m_threadActive)
window->ProcessEvents(true);
DestroyWindow(*handle);
DestroyWindow(winHandle);
}
#endif

View File

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