2 Commits

Author SHA1 Message Date
d1str4ught
35c183bd66 storing blend modes and color operation before for each buffer 2025-08-27 23:44:37 +02:00
d1str4ught
5db6e9c3d9 particle batching almost good 2025-08-26 03:18:09 +02:00
1123 changed files with 47505 additions and 292995 deletions

1
.gitattributes vendored
View File

@@ -0,0 +1 @@
*.lib filter=lfs diff=lfs merge=lfs -text

View File

@@ -1,35 +0,0 @@
name: build
on:
push:
branches:
- main
jobs:
win:
name: "Windows Build"
runs-on: windows-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Build project
id: build_project
shell: pwsh
working-directory: ${{ github.workspace }}
run: |
mkdir build
cd build
cmake ..
cmake --build . --config RelWithDebInfo
- name: Collect outputs
run: |
mkdir _output
cp build/bin/* _output
- name: Upload
uses: actions/upload-artifact@v4
with:
name: output_win
path: _output

64
.gitignore vendored
View File

@@ -1,63 +1 @@
/build/ build
# =======================================================
# FULLY CASE-INSENSITIVE BACKUP EXCLUSIONS
# Matches all files and folders ending in:
# _BK, _BAK, .BK, .BAK (and all case permutations)
# =======================================================
# -------------------------------------------------------
# 1. EXCLUSIONS ENDING IN .BK / _BK
# -------------------------------------------------------
# Files/Folders ending in _BK (e.g., File_Bk, Folder_bK)
*_BK
*_Bk
*_bK
*_bk
# Files ending in .BK (e.g., File.BK, File.bK)
*.BK
*.Bk
*.bK
*.bk
# Files ending in "double extension" .X.BK (e.g., File.txt.Bk)
*.*.BK
*.*.Bk
*.*.bK
*.*.bk
# -------------------------------------------------------
# 2. EXCLUSIONS ENDING IN .BAK / _BAK
# -------------------------------------------------------
# Files/Folders ending in _BAK (e.g., File_BAK, Folder_bak)
*_BAK
*_BAk
*_BaK
*_Bak
*_bAK
*_bAk
*_baK
*_bak
# Files ending in .BAK (e.g., File.BAK, File.bak)
*.BAK
*.BAk
*.BaK
*.Bak
*.bAK
*.bAk
*.baK
*.bak
# Files ending in "double extension" .X.BAK (e.g., File.txt.Bak)
*.*.BAK
*.*.BAk
*.*.BaK
*.*.Bak
*.*.bAK
*.*.bAk
*.*.baK
*.*.bak

View File

@@ -2,12 +2,9 @@
project(m2dev-client-src) project(m2dev-client-src)
set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
# ASan support
option(ENABLE_ASAN "Enable AddressSanitizer" OFF)
set(CMAKE_MODULE_PATH set(CMAKE_MODULE_PATH
${CMAKE_MODULE_PATH} ${CMAKE_MODULE_PATH}
"${CMAKE_CURRENT_SOURCE_DIR}/buildtool" "${CMAKE_CURRENT_SOURCE_DIR}/buildtool"
@@ -26,28 +23,11 @@ set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /DEBUG")
add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/utf-8>") add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/utf-8>")
add_compile_options(/MP) add_compile_options(/MP)
if(MSVC)
add_compile_definitions(UNICODE _UNICODE)
endif()
add_compile_options( add_compile_options(
$<$<CXX_COMPILER_ID:MSVC>:/wd4828> $<$<CXX_COMPILER_ID:MSVC>:/wd4828>
$<$<CXX_COMPILER_ID:MSVC>:/wd4996> $<$<CXX_COMPILER_ID:MSVC>:/wd4996>
) )
# ASan flags
if(ENABLE_ASAN)
if(MSVC)
add_compile_options(/fsanitize=address)
add_link_options(/fsanitize=address)
add_definitions(-D_DISABLE_VECTOR_ANNOTATION)
add_definitions(-D_DISABLE_STRING_ANNOTATION)
else()
add_compile_options(-fsanitize=address -fno-omit-frame-pointer)
add_link_options(-fsanitize=address)
endif()
endif()
add_definitions(-DNOMINMAX) add_definitions(-DNOMINMAX)
add_definitions(-DWIN32_LEAN_AND_MEAN) add_definitions(-DWIN32_LEAN_AND_MEAN)
add_definitions(-D_CRT_SECURE_NO_WARNINGS) add_definitions(-D_CRT_SECURE_NO_WARNINGS)

View File

@@ -1,19 +1 @@
# Client Source Repository # m2dev-client-src
This repository contains the source code necessary to compile the game client executable.
## How to build
> cmake -S . -B build
>
> cmake --build build
---
## 📋 Changelog
### 🐛 Bug Fixes
* **Amun's freeze on drag window**: Fixed a bug where the client window would freeze while we are dragging it around.
* **Debug mode:** Fly effects are now registering when using Debug mode.
* **Fix effect rendering in low opacity models:** Effects now appear normally on semi-transparent meshes.
* **Fly targeting fixed for buff/healing skills:** Fixed an issue where fly target effect would render in the buffer's selected target even if the target was unbuffable (if viewing from another client).

8421
extern/include/MSS.H vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,2 +0,0 @@
#define MINIAUDIO_IMPLEMENTATION
#include "miniaudio.h"

File diff suppressed because it is too large Load Diff

View File

@@ -1,666 +0,0 @@
/*
* PCG Random Number Generation for C++
*
* Copyright 2014-2017 Melissa O'Neill <oneill@pcg-random.org>,
* and the PCG Project contributors.
*
* SPDX-License-Identifier: (Apache-2.0 OR MIT)
*
* Licensed under the Apache License, Version 2.0 (provided in
* LICENSE-APACHE.txt and at http://www.apache.org/licenses/LICENSE-2.0)
* or under the MIT license (provided in LICENSE-MIT.txt and at
* http://opensource.org/licenses/MIT), at your option. This file may not
* be copied, modified, or distributed except according to those terms.
*
* Distributed on an "AS IS" BASIS, WITHOUT WARRANTY OF ANY KIND, either
* express or implied. See your chosen license for details.
*
* For additional information about the PCG random number generation scheme,
* visit http://www.pcg-random.org/.
*/
/*
* This file provides support code that is useful for random-number generation
* but not specific to the PCG generation scheme, including:
* - 128-bit int support for platforms where it isn't available natively
* - bit twiddling operations
* - I/O of 128-bit and 8-bit integers
* - Handling the evilness of SeedSeq
* - Support for efficiently producing random numbers less than a given
* bound
*/
#ifndef PCG_EXTRAS_HPP_INCLUDED
#define PCG_EXTRAS_HPP_INCLUDED 1
#include <cinttypes>
#include <cstddef>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <limits>
#include <iostream>
#include <type_traits>
#include <utility>
#include <locale>
#include <iterator>
#ifdef __GNUC__
#include <cxxabi.h>
#endif
/*
* Abstractions for compiler-specific directives
*/
#ifdef __GNUC__
#define PCG_NOINLINE __attribute__((noinline))
#else
#define PCG_NOINLINE
#endif
/*
* Some members of the PCG library use 128-bit math. When compiling on 64-bit
* platforms, both GCC and Clang provide 128-bit integer types that are ideal
* for the job.
*
* On 32-bit platforms (or with other compilers), we fall back to a C++
* class that provides 128-bit unsigned integers instead. It may seem
* like we're reinventing the wheel here, because libraries already exist
* that support large integers, but most existing libraries provide a very
* generic multiprecision code, but here we're operating at a fixed size.
* Also, most other libraries are fairly heavyweight. So we use a direct
* implementation. Sadly, it's much slower than hand-coded assembly or
* direct CPU support.
*
*/
#if __SIZEOF_INT128__ && !PCG_FORCE_EMULATED_128BIT_MATH
namespace pcg_extras {
typedef __uint128_t pcg128_t;
}
#define PCG_128BIT_CONSTANT(high,low) \
((pcg_extras::pcg128_t(high) << 64) + low)
#else
#include "pcg_uint128.hpp"
namespace pcg_extras {
typedef pcg_extras::uint_x4<uint32_t,uint64_t> pcg128_t;
}
#define PCG_128BIT_CONSTANT(high,low) \
pcg_extras::pcg128_t(high,low)
#define PCG_EMULATED_128BIT_MATH 1
#endif
namespace pcg_extras {
/*
* We often need to represent a "number of bits". When used normally, these
* numbers are never greater than 128, so an unsigned char is plenty.
* If you're using a nonstandard generator of a larger size, you can set
* PCG_BITCOUNT_T to have it define it as a larger size. (Some compilers
* might produce faster code if you set it to an unsigned int.)
*/
#ifndef PCG_BITCOUNT_T
typedef uint8_t bitcount_t;
#else
typedef PCG_BITCOUNT_T bitcount_t;
#endif
/*
* C++ requires us to be able to serialize RNG state by printing or reading
* it from a stream. Because we use 128-bit ints, we also need to be able
* ot print them, so here is code to do so.
*
* This code provides enough functionality to print 128-bit ints in decimal
* and zero-padded in hex. It's not a full-featured implementation.
*/
template <typename CharT, typename Traits>
std::basic_ostream<CharT,Traits>&
operator<<(std::basic_ostream<CharT,Traits>& out, pcg128_t value)
{
auto desired_base = out.flags() & out.basefield;
bool want_hex = desired_base == out.hex;
if (want_hex) {
uint64_t highpart = uint64_t(value >> 64);
uint64_t lowpart = uint64_t(value);
auto desired_width = out.width();
if (desired_width > 16) {
out.width(desired_width - 16);
}
if (highpart != 0 || desired_width > 16)
out << highpart;
CharT oldfill = '\0';
if (highpart != 0) {
out.width(16);
oldfill = out.fill('0');
}
auto oldflags = out.setf(decltype(desired_base){}, out.showbase);
out << lowpart;
out.setf(oldflags);
if (highpart != 0) {
out.fill(oldfill);
}
return out;
}
constexpr size_t MAX_CHARS_128BIT = 40;
char buffer[MAX_CHARS_128BIT];
char* pos = buffer+sizeof(buffer);
*(--pos) = '\0';
constexpr auto BASE = pcg128_t(10ULL);
do {
auto div = value / BASE;
auto mod = uint32_t(value - (div * BASE));
*(--pos) = '0' + char(mod);
value = div;
} while(value != pcg128_t(0ULL));
return out << pos;
}
template <typename CharT, typename Traits>
std::basic_istream<CharT,Traits>&
operator>>(std::basic_istream<CharT,Traits>& in, pcg128_t& value)
{
typename std::basic_istream<CharT,Traits>::sentry s(in);
if (!s)
return in;
constexpr auto BASE = pcg128_t(10ULL);
pcg128_t current(0ULL);
bool did_nothing = true;
bool overflow = false;
for(;;) {
CharT wide_ch = in.get();
if (!in.good()) {
in.clear(std::ios::eofbit);
break;
}
auto ch = in.narrow(wide_ch, '\0');
if (ch < '0' || ch > '9') {
in.unget();
break;
}
did_nothing = false;
pcg128_t digit(uint32_t(ch - '0'));
pcg128_t timesbase = current*BASE;
overflow = overflow || timesbase < current;
current = timesbase + digit;
overflow = overflow || current < digit;
}
if (did_nothing || overflow) {
in.setstate(std::ios::failbit);
if (overflow)
current = ~pcg128_t(0ULL);
}
value = current;
return in;
}
/*
* Likewise, if people use tiny rngs, we'll be serializing uint8_t.
* If we just used the provided IO operators, they'd read/write chars,
* not ints, so we need to define our own. We *can* redefine this operator
* here because we're in our own namespace.
*/
template <typename CharT, typename Traits>
std::basic_ostream<CharT,Traits>&
operator<<(std::basic_ostream<CharT,Traits>&out, uint8_t value)
{
return out << uint32_t(value);
}
template <typename CharT, typename Traits>
std::basic_istream<CharT,Traits>&
operator>>(std::basic_istream<CharT,Traits>& in, uint8_t& target)
{
uint32_t value = 0xdecea5edU;
in >> value;
if (!in && value == 0xdecea5edU)
return in;
if (value > uint8_t(~0)) {
in.setstate(std::ios::failbit);
value = ~0U;
}
target = uint8_t(value);
return in;
}
/* Unfortunately, the above functions don't get found in preference to the
* built in ones, so we create some more specific overloads that will.
* Ugh.
*/
inline std::ostream& operator<<(std::ostream& out, uint8_t value)
{
return pcg_extras::operator<< <char>(out, value);
}
inline std::istream& operator>>(std::istream& in, uint8_t& value)
{
return pcg_extras::operator>> <char>(in, value);
}
/*
* Useful bitwise operations.
*/
/*
* XorShifts are invertable, but they are someting of a pain to invert.
* This function backs them out. It's used by the whacky "inside out"
* generator defined later.
*/
template <typename itype>
inline itype unxorshift(itype x, bitcount_t bits, bitcount_t shift)
{
if (2*shift >= bits) {
return x ^ (x >> shift);
}
itype lowmask1 = (itype(1U) << (bits - shift*2)) - 1;
itype highmask1 = ~lowmask1;
itype top1 = x;
itype bottom1 = x & lowmask1;
top1 ^= top1 >> shift;
top1 &= highmask1;
x = top1 | bottom1;
itype lowmask2 = (itype(1U) << (bits - shift)) - 1;
itype bottom2 = x & lowmask2;
bottom2 = unxorshift(bottom2, bits - shift, shift);
bottom2 &= lowmask1;
return top1 | bottom2;
}
/*
* Rotate left and right.
*
* In ideal world, compilers would spot idiomatic rotate code and convert it
* to a rotate instruction. Of course, opinions vary on what the correct
* idiom is and how to spot it. For clang, sometimes it generates better
* (but still crappy) code if you define PCG_USE_ZEROCHECK_ROTATE_IDIOM.
*/
template <typename itype>
inline itype rotl(itype value, bitcount_t rot)
{
constexpr bitcount_t bits = sizeof(itype) * 8;
constexpr bitcount_t mask = bits - 1;
#if PCG_USE_ZEROCHECK_ROTATE_IDIOM
return rot ? (value << rot) | (value >> (bits - rot)) : value;
#else
return (value << rot) | (value >> ((- rot) & mask));
#endif
}
template <typename itype>
inline itype rotr(itype value, bitcount_t rot)
{
constexpr bitcount_t bits = sizeof(itype) * 8;
constexpr bitcount_t mask = bits - 1;
#if PCG_USE_ZEROCHECK_ROTATE_IDIOM
return rot ? (value >> rot) | (value << (bits - rot)) : value;
#else
return (value >> rot) | (value << ((- rot) & mask));
#endif
}
/* Unfortunately, both Clang and GCC sometimes perform poorly when it comes
* to properly recognizing idiomatic rotate code, so for we also provide
* assembler directives (enabled with PCG_USE_INLINE_ASM). Boo, hiss.
* (I hope that these compilers get better so that this code can die.)
*
* These overloads will be preferred over the general template code above.
*/
#if PCG_USE_INLINE_ASM && __GNUC__ && (__x86_64__ || __i386__)
inline uint8_t rotr(uint8_t value, bitcount_t rot)
{
asm ("rorb %%cl, %0" : "=r" (value) : "0" (value), "c" (rot));
return value;
}
inline uint16_t rotr(uint16_t value, bitcount_t rot)
{
asm ("rorw %%cl, %0" : "=r" (value) : "0" (value), "c" (rot));
return value;
}
inline uint32_t rotr(uint32_t value, bitcount_t rot)
{
asm ("rorl %%cl, %0" : "=r" (value) : "0" (value), "c" (rot));
return value;
}
#if __x86_64__
inline uint64_t rotr(uint64_t value, bitcount_t rot)
{
asm ("rorq %%cl, %0" : "=r" (value) : "0" (value), "c" (rot));
return value;
}
#endif // __x86_64__
#elif defined(_MSC_VER)
// Use MSVC++ bit rotation intrinsics
#pragma intrinsic(_rotr, _rotr64, _rotr8, _rotr16)
inline uint8_t rotr(uint8_t value, bitcount_t rot)
{
return _rotr8(value, rot);
}
inline uint16_t rotr(uint16_t value, bitcount_t rot)
{
return _rotr16(value, rot);
}
inline uint32_t rotr(uint32_t value, bitcount_t rot)
{
return _rotr(value, rot);
}
inline uint64_t rotr(uint64_t value, bitcount_t rot)
{
return _rotr64(value, rot);
}
#endif // PCG_USE_INLINE_ASM
/*
* The C++ SeedSeq concept (modelled by seed_seq) can fill an array of
* 32-bit integers with seed data, but sometimes we want to produce
* larger or smaller integers.
*
* The following code handles this annoyance.
*
* uneven_copy will copy an array of 32-bit ints to an array of larger or
* smaller ints (actually, the code is general it only needing forward
* iterators). The copy is identical to the one that would be performed if
* we just did memcpy on a standard little-endian machine, but works
* regardless of the endian of the machine (or the weirdness of the ints
* involved).
*
* generate_to initializes an array of integers using a SeedSeq
* object. It is given the size as a static constant at compile time and
* tries to avoid memory allocation. If we're filling in 32-bit constants
* we just do it directly. If we need a separate buffer and it's small,
* we allocate it on the stack. Otherwise, we fall back to heap allocation.
* Ugh.
*
* generate_one produces a single value of some integral type using a
* SeedSeq object.
*/
/* uneven_copy helper, case where destination ints are less than 32 bit. */
template<class SrcIter, class DestIter>
SrcIter uneven_copy_impl(
SrcIter src_first, DestIter dest_first, DestIter dest_last,
std::true_type)
{
typedef typename std::iterator_traits<SrcIter>::value_type src_t;
typedef typename std::iterator_traits<DestIter>::value_type dest_t;
constexpr bitcount_t SRC_SIZE = sizeof(src_t);
constexpr bitcount_t DEST_SIZE = sizeof(dest_t);
constexpr bitcount_t DEST_BITS = DEST_SIZE * 8;
constexpr bitcount_t SCALE = SRC_SIZE / DEST_SIZE;
size_t count = 0;
src_t value = 0;
while (dest_first != dest_last) {
if ((count++ % SCALE) == 0)
value = *src_first++; // Get more bits
else
value >>= DEST_BITS; // Move down bits
*dest_first++ = dest_t(value); // Truncates, ignores high bits.
}
return src_first;
}
/* uneven_copy helper, case where destination ints are more than 32 bit. */
template<class SrcIter, class DestIter>
SrcIter uneven_copy_impl(
SrcIter src_first, DestIter dest_first, DestIter dest_last,
std::false_type)
{
typedef typename std::iterator_traits<SrcIter>::value_type src_t;
typedef typename std::iterator_traits<DestIter>::value_type dest_t;
constexpr auto SRC_SIZE = sizeof(src_t);
constexpr auto SRC_BITS = SRC_SIZE * 8;
constexpr auto DEST_SIZE = sizeof(dest_t);
constexpr auto SCALE = (DEST_SIZE+SRC_SIZE-1) / SRC_SIZE;
while (dest_first != dest_last) {
dest_t value(0UL);
unsigned int shift = 0;
for (size_t i = 0; i < SCALE; ++i) {
value |= dest_t(*src_first++) << shift;
shift += SRC_BITS;
}
*dest_first++ = value;
}
return src_first;
}
/* uneven_copy, call the right code for larger vs. smaller */
template<class SrcIter, class DestIter>
inline SrcIter uneven_copy(SrcIter src_first,
DestIter dest_first, DestIter dest_last)
{
typedef typename std::iterator_traits<SrcIter>::value_type src_t;
typedef typename std::iterator_traits<DestIter>::value_type dest_t;
constexpr bool DEST_IS_SMALLER = sizeof(dest_t) < sizeof(src_t);
return uneven_copy_impl(src_first, dest_first, dest_last,
std::integral_constant<bool, DEST_IS_SMALLER>{});
}
/* generate_to, fill in a fixed-size array of integral type using a SeedSeq
* (actually works for any random-access iterator)
*/
template <size_t size, typename SeedSeq, typename DestIter>
inline void generate_to_impl(SeedSeq&& generator, DestIter dest,
std::true_type)
{
generator.generate(dest, dest+size);
}
template <size_t size, typename SeedSeq, typename DestIter>
void generate_to_impl(SeedSeq&& generator, DestIter dest,
std::false_type)
{
typedef typename std::iterator_traits<DestIter>::value_type dest_t;
constexpr auto DEST_SIZE = sizeof(dest_t);
constexpr auto GEN_SIZE = sizeof(uint32_t);
constexpr bool GEN_IS_SMALLER = GEN_SIZE < DEST_SIZE;
constexpr size_t FROM_ELEMS =
GEN_IS_SMALLER
? size * ((DEST_SIZE+GEN_SIZE-1) / GEN_SIZE)
: (size + (GEN_SIZE / DEST_SIZE) - 1)
/ ((GEN_SIZE / DEST_SIZE) + GEN_IS_SMALLER);
// this odd code ^^^^^^^^^^^^^^^^^ is work-around for
// a bug: http://llvm.org/bugs/show_bug.cgi?id=21287
if (FROM_ELEMS <= 1024) {
uint32_t buffer[FROM_ELEMS];
generator.generate(buffer, buffer+FROM_ELEMS);
uneven_copy(buffer, dest, dest+size);
} else {
uint32_t* buffer = static_cast<uint32_t*>(malloc(GEN_SIZE * FROM_ELEMS));
generator.generate(buffer, buffer+FROM_ELEMS);
uneven_copy(buffer, dest, dest+size);
free(static_cast<void*>(buffer));
}
}
template <size_t size, typename SeedSeq, typename DestIter>
inline void generate_to(SeedSeq&& generator, DestIter dest)
{
typedef typename std::iterator_traits<DestIter>::value_type dest_t;
constexpr bool IS_32BIT = sizeof(dest_t) == sizeof(uint32_t);
generate_to_impl<size>(std::forward<SeedSeq>(generator), dest,
std::integral_constant<bool, IS_32BIT>{});
}
/* generate_one, produce a value of integral type using a SeedSeq
* (optionally, we can have it produce more than one and pick which one
* we want)
*/
template <typename UInt, size_t i = 0UL, size_t N = i+1UL, typename SeedSeq>
inline UInt generate_one(SeedSeq&& generator)
{
UInt result[N];
generate_to<N>(std::forward<SeedSeq>(generator), result);
return result[i];
}
template <typename RngType>
auto bounded_rand(RngType& rng, typename RngType::result_type upper_bound)
-> typename RngType::result_type
{
typedef typename RngType::result_type rtype;
rtype threshold = (RngType::max() - RngType::min() + rtype(1) - upper_bound)
% upper_bound;
for (;;) {
rtype r = rng() - RngType::min();
if (r >= threshold)
return r % upper_bound;
}
}
template <typename Iter, typename RandType>
void shuffle(Iter from, Iter to, RandType&& rng)
{
typedef typename std::iterator_traits<Iter>::difference_type delta_t;
typedef typename std::remove_reference<RandType>::type::result_type result_t;
auto count = to - from;
while (count > 1) {
delta_t chosen = delta_t(bounded_rand(rng, result_t(count)));
--count;
--to;
using std::swap;
swap(*(from + chosen), *to);
}
}
/*
* Although std::seed_seq is useful, it isn't everything. Often we want to
* initialize a random-number generator some other way, such as from a random
* device.
*
* Technically, it does not meet the requirements of a SeedSequence because
* it lacks some of the rarely-used member functions (some of which would
* be impossible to provide). However the C++ standard is quite specific
* that actual engines only called the generate method, so it ought not to be
* a problem in practice.
*/
template <typename RngType>
class seed_seq_from {
private:
RngType rng_;
typedef uint_least32_t result_type;
public:
template<typename... Args>
seed_seq_from(Args&&... args) :
rng_(std::forward<Args>(args)...)
{
// Nothing (else) to do...
}
template<typename Iter>
void generate(Iter start, Iter finish)
{
for (auto i = start; i != finish; ++i)
*i = result_type(rng_());
}
constexpr size_t size() const
{
return (sizeof(typename RngType::result_type) > sizeof(result_type)
&& RngType::max() > ~size_t(0UL))
? ~size_t(0UL)
: size_t(RngType::max());
}
};
/*
* Sometimes you might want a distinct seed based on when the program
* was compiled. That way, a particular instance of the program will
* behave the same way, but when recompiled it'll produce a different
* value.
*/
template <typename IntType>
struct static_arbitrary_seed {
private:
static constexpr IntType fnv(IntType hash, const char* pos) {
return *pos == '\0'
? hash
: fnv((hash * IntType(16777619U)) ^ *pos, (pos+1));
}
public:
static constexpr IntType value = fnv(IntType(2166136261U ^ sizeof(IntType)),
__DATE__ __TIME__ __FILE__);
};
// Sometimes, when debugging or testing, it's handy to be able print the name
// of a (in human-readable form). This code allows the idiom:
//
// cout << printable_typename<my_foo_type_t>()
//
// to print out my_foo_type_t (or its concrete type if it is a synonym)
#if __cpp_rtti || __GXX_RTTI
template <typename T>
struct printable_typename {};
template <typename T>
std::ostream& operator<<(std::ostream& out, printable_typename<T>) {
const char *implementation_typename = typeid(T).name();
#ifdef __GNUC__
int status;
char* pretty_name =
abi::__cxa_demangle(implementation_typename, nullptr, nullptr, &status);
if (status == 0)
out << pretty_name;
free(static_cast<void*>(pretty_name));
if (status == 0)
return out;
#endif
out << implementation_typename;
return out;
}
#endif // __cpp_rtti || __GXX_RTTI
} // namespace pcg_extras
#endif // PCG_EXTRAS_HPP_INCLUDED

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

840
extern/include/utf8.h vendored
View File

@@ -1,840 +0,0 @@
#pragma once
#include <string>
#include <windows.h>
#include <vector>
#include <algorithm>
#include <cmath>
#include <EterLocale/Arabic.h>
// ============================================================================
// CONFIGURATION CONSTANTS
// ============================================================================
// Maximum text length for security/performance (prevent DoS attacks)
constexpr size_t MAX_TEXT_LENGTH = 65536; // 64KB of text
constexpr size_t MAX_CHAT_TEXT_LENGTH = 4096; // 4KB for chat messages
// Arabic shaping buffer size calculations
constexpr size_t ARABIC_SHAPING_EXPANSION_FACTOR = 2;
constexpr size_t ARABIC_SHAPING_SAFETY_MARGIN = 16;
constexpr size_t ARABIC_SHAPING_EXPANSION_FACTOR_RETRY = 4;
constexpr size_t ARABIC_SHAPING_SAFETY_MARGIN_RETRY = 64;
// ============================================================================
// DEBUG LOGGING (Only enabled in Debug builds)
// ============================================================================
#ifdef _DEBUG
#define DEBUG_BIDI // Enabled in debug builds for diagnostics
#endif
#ifdef DEBUG_BIDI
#include <cstdio>
#define BIDI_LOG(fmt, ...) printf("[BiDi] " fmt "\n", __VA_ARGS__)
#define BIDI_LOG_SIMPLE(msg) printf("[BiDi] %s\n", msg)
#else
#define BIDI_LOG(fmt, ...) ((void)0)
#define BIDI_LOG_SIMPLE(msg) ((void)0)
#endif
// ============================================================================
// UNICODE VALIDATION HELPERS
// ============================================================================
// Check if codepoint is a valid Unicode scalar value (not surrogate, not non-character)
static inline bool IsValidUnicodeScalar(wchar_t ch)
{
// Reject surrogate pairs (UTF-16 encoding artifacts, invalid in UTF-8)
if (ch >= 0xD800 && ch <= 0xDFFF)
return false;
// Reject non-characters (reserved by Unicode standard)
if ((ch >= 0xFDD0 && ch <= 0xFDEF) || // Arabic Presentation Forms non-chars
(ch & 0xFFFE) == 0xFFFE) // U+FFFE, U+FFFF, etc.
return false;
// Accept everything else in BMP (0x0000-0xFFFF)
return true;
}
// Sanitize a wide string by removing invalid Unicode codepoints
static inline void SanitizeWideString(std::wstring& ws)
{
ws.erase(std::remove_if(ws.begin(), ws.end(),
[](wchar_t ch) { return !IsValidUnicodeScalar(ch); }),
ws.end());
}
// UTF-8 -> UTF-16 (Windows wide)
inline std::wstring Utf8ToWide(const std::string& s)
{
if (s.empty())
return L"";
// Validate size limits (prevent DoS and INT_MAX overflow)
if (s.size() > MAX_TEXT_LENGTH || s.size() > INT_MAX)
{
BIDI_LOG("Utf8ToWide: String too large (%zu bytes)", s.size());
return L""; // String too large
}
int wlen = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), (int)s.size(), nullptr, 0);
if (wlen <= 0)
{
BIDI_LOG("Utf8ToWide: Invalid UTF-8 sequence (error %d)", GetLastError());
return L"";
}
std::wstring out(wlen, L'\0');
int written = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), (int)s.size(), out.data(), wlen);
if (written <= 0 || written != wlen)
{
BIDI_LOG("Utf8ToWide: Second conversion failed (written=%d, expected=%d, error=%d)", written, wlen, GetLastError());
return L""; // Conversion failed unexpectedly
}
// Optional: Sanitize to remove invalid Unicode codepoints (surrogates, non-characters)
// Uncomment if you want strict validation
// SanitizeWideString(out);
return out;
}
// Convenience overload for char*
inline std::wstring Utf8ToWide(const char* s)
{
if (!s || !*s)
return L"";
int wlen = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, s, -1, nullptr, 0);
if (wlen <= 0)
return L"";
// wlen includes terminating NUL
std::wstring out(wlen, L'\0');
int written = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, s, -1, out.data(), wlen);
if (written <= 0 || written != wlen)
{
BIDI_LOG("Utf8ToWide(char*): Conversion failed (written=%d, expected=%d, error=%d)", written, wlen, GetLastError());
return L"";
}
// Drop the terminating NUL from std::wstring length
if (!out.empty() && out.back() == L'\0')
out.pop_back();
// Optional: Sanitize to remove invalid Unicode codepoints
// SanitizeWideString(out);
return out;
}
// UTF-16 (Windows wide) -> UTF-8
inline std::string WideToUtf8(const std::wstring& ws)
{
if (ws.empty())
return "";
// Validate size limits (prevent DoS and INT_MAX overflow)
if (ws.size() > MAX_TEXT_LENGTH || ws.size() > INT_MAX)
return ""; // String too large
int len = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, ws.data(), (int)ws.size(), nullptr, 0, nullptr, nullptr);
if (len <= 0)
return "";
std::string out(len, '\0');
int written = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, ws.data(), (int)ws.size(), out.data(), len, nullptr, nullptr);
if (written <= 0 || written != len)
{
BIDI_LOG("WideToUtf8: Conversion failed (written=%d, expected=%d, error=%d)", written, len, GetLastError());
return ""; // Conversion failed
}
return out;
}
// Convenience overload for wchar_t*
inline std::string WideToUtf8(const wchar_t* ws)
{
if (!ws)
return "";
return WideToUtf8(std::wstring(ws));
}
// ============================================================================
// RTL & BiDi formatting for RTL UI
// ============================================================================
enum class EBidiDir { LTR, RTL };
enum class ECharDir : unsigned char { Neutral, LTR, RTL };
struct TBidiRun
{
EBidiDir dir;
std::vector<wchar_t> text; // logical order
};
static inline bool IsRTLCodepoint(wchar_t ch)
{
// Directional marks / isolates / embeddings that affect bidi
if (ch == 0x200F || ch == 0x061C) return true; // RLM, ALM
if (ch >= 0x202B && ch <= 0x202E) return true; // RLE/RLO/PDF/LRE/LRO
if (ch >= 0x2066 && ch <= 0x2069) return true; // isolates
// Hebrew + Arabic blocks (BMP)
if (ch >= 0x0590 && ch <= 0x08FF) return true;
// Presentation forms
if (ch >= 0xFB1D && ch <= 0xFDFF) return true;
if (ch >= 0xFE70 && ch <= 0xFEFF) return true;
return false;
}
static inline bool IsStrongAlpha(wchar_t ch)
{
// Use thread-local cache for BMP (Thread safety)
thread_local static unsigned char cache[65536] = {}; // 0=unknown, 1=true, 2=false
unsigned char& v = cache[(unsigned short)ch];
if (v == 1) return true;
if (v == 2) return false;
WORD type = 0;
bool ok = GetStringTypeW(CT_CTYPE1, &ch, 1, &type) && (type & C1_ALPHA);
v = ok ? 1 : 2;
return ok;
}
static inline bool IsDigit(wchar_t ch)
{
// Fast path for ASCII digits (90%+ of digit checks)
if (ch >= L'0' && ch <= L'9')
return true;
// For non-ASCII, use cache (Arabic-Indic digits, etc.)
thread_local static unsigned char cache[65536] = {}; // 0=unknown, 1=true, 2=false
unsigned char& v = cache[(unsigned short)ch];
if (v == 1) return true;
if (v == 2) return false;
WORD type = 0;
bool ok = GetStringTypeW(CT_CTYPE1, &ch, 1, &type) && (type & C1_DIGIT);
v = ok ? 1 : 2;
return ok;
}
static inline bool IsNameTokenPunct(wchar_t ch)
{
switch (ch)
{
case L'#':
case L'@':
case L'$':
case L'%':
case L'&':
case L'*':
case L'+':
case L'-':
case L'_':
case L'=':
case L'.':
case L',':
case L'/':
case L'\\':
case L'(':
case L')':
// Brackets are handled specially - see GetCharDirSmart
// case L'[':
// case L']':
case L'{':
case L'}':
case L'<':
case L'>':
return true;
default:
return false;
}
}
// Check RTL first to avoid classifying Arabic as LTR
static inline bool IsStrongLTR(wchar_t ch)
{
if (IsRTLCodepoint(ch))
return false;
return IsStrongAlpha(ch) || IsDigit(ch);
}
static inline bool HasStrongLTRNeighbor(const wchar_t* s, int n, int i)
{
// Skip neutral characters (spaces, punctuation) to find nearest strong character
// This fixes mixed-direction text like "english + arabic"
// Search backwards for strong character (skip neutrals/whitespace)
for (int j = i - 1; j >= 0; --j)
{
wchar_t ch = s[j];
// Skip spaces and common neutral punctuation
if (ch == L' ' || ch == L'\t' || ch == L'\n')
continue;
// Found strong LTR
if (IsStrongLTR(ch))
return true;
// Found strong RTL or other strong character
if (IsRTLCodepoint(ch) || IsStrongAlpha(ch))
break;
}
// Search forwards for strong character (skip neutrals/whitespace)
for (int j = i + 1; j < n; ++j)
{
wchar_t ch = s[j];
// Skip spaces and common neutral punctuation
if (ch == L' ' || ch == L'\t' || ch == L'\n')
continue;
// Found strong LTR
if (IsStrongLTR(ch))
return true;
// Found strong RTL or other strong character
if (IsRTLCodepoint(ch) || IsStrongAlpha(ch))
break;
}
return false;
}
static inline ECharDir GetCharDir(wchar_t ch)
{
if (IsRTLCodepoint(ch))
return ECharDir::RTL;
// Use IsStrongLTR which now correctly excludes RTL
if (IsStrongLTR(ch))
return ECharDir::LTR;
return ECharDir::Neutral;
}
static inline ECharDir GetCharDirSmart(const wchar_t* s, int n, int i)
{
wchar_t ch = s[i];
// True RTL letters/marks
if (IsRTLCodepoint(ch))
return ECharDir::RTL;
// True LTR letters/digits (now correctly excludes RTL)
if (IsStrongLTR(ch))
return ECharDir::LTR;
// Parentheses: always LTR to keep them with their content
if (ch == L'(' || ch == L')')
return ECharDir::LTR;
// Common punctuation: treat as strong LTR to prevent jumping around in mixed text
// This makes "Hello + اختبار" and "اختبار + Hello" both keep punctuation in place
if (ch == L'+' || ch == L'-' || ch == L'=' || ch == L'*' || ch == L'/' ||
ch == L'<' || ch == L'>' || ch == L'&' || ch == L'|' || ch == L'@' || ch == L'#')
return ECharDir::LTR;
// Percentage sign: attach to numbers (scan nearby for digits/minus/plus)
// Handles: "%20", "20%", "-6%", "%d%%", etc.
if (ch == L'%')
{
// Look backward for digit, %, -, or +
for (int j = i - 1; j >= 0 && (i - j) < 5; --j)
{
wchar_t prev = s[j];
if (IsDigit(prev) || prev == L'%' || prev == L'-' || prev == L'+')
return ECharDir::LTR;
if (prev != L' ' && prev != L'\t')
break; // Stop if we hit non-numeric character
}
// Look forward for digit, %, -, or +
for (int j = i + 1; j < n && (j - i) < 5; ++j)
{
wchar_t next = s[j];
if (IsDigit(next) || next == L'%' || next == L'-' || next == L'+')
return ECharDir::LTR;
if (next != L' ' && next != L'\t')
break; // Stop if we hit non-numeric character
}
return ECharDir::Neutral;
}
// Minus/dash: attach to numbers (scan nearby for digits/%)
// Handles: "-6", "5-10", "-6%%", etc.
if (ch == L'-')
{
// Look backward for digit or %
for (int j = i - 1; j >= 0 && (i - j) < 3; --j)
{
wchar_t prev = s[j];
if (IsDigit(prev) || prev == L'%')
return ECharDir::LTR;
if (prev != L' ' && prev != L'\t')
break;
}
// Look forward for digit or %
for (int j = i + 1; j < n && (j - i) < 3; ++j)
{
wchar_t next = s[j];
if (IsDigit(next) || next == L'%')
return ECharDir::LTR;
if (next != L' ' && next != L'\t')
break;
}
return ECharDir::Neutral;
}
// Colon: attach to preceding text direction
// Look backward to find strong character
if (ch == L':')
{
for (int j = i - 1; j >= 0; --j)
{
if (s[j] == L' ' || s[j] == L'\t')
continue; // Skip spaces
if (IsRTLCodepoint(s[j]))
return ECharDir::RTL; // Attach to RTL text
if (IsStrongLTR(s[j]))
return ECharDir::LTR; // Attach to LTR text
}
return ECharDir::Neutral;
}
// Enhancement marker: '+' followed by digit(s) should attach to preceding text
// If preceded by RTL, treat as RTL to keep "+9" with the item name
// Otherwise treat as LTR
if (ch == L'+' && i + 1 < n && IsDigit(s[i + 1]))
{
// Look backward for the last strong character
for (int j = i - 1; j >= 0; --j)
{
if (IsRTLCodepoint(s[j]))
return ECharDir::RTL; // Attach to preceding RTL text
if (IsStrongLTR(s[j]))
return ECharDir::LTR; // Attach to preceding LTR text
// Skip neutral characters
}
return ECharDir::LTR; // Default to LTR if no strong character found
}
// Brackets: always attach to the content inside them
// This fixes hyperlinks like "[درع فولاذي أسود+9]"
if (ch == L'[' || ch == L']')
{
// Opening bracket '[': look forward for strong character
if (ch == L'[')
{
for (int j = i + 1; j < n; ++j)
{
wchar_t next = s[j];
if (next == L']') break; // End of bracket content
if (IsRTLCodepoint(next)) return ECharDir::RTL;
if (IsStrongLTR(next)) return ECharDir::LTR;
}
}
// Closing bracket ']': look backward for strong character
else if (ch == L']')
{
for (int j = i - 1; j >= 0; --j)
{
wchar_t prev = s[j];
if (prev == L'[') break; // Start of bracket content
if (IsRTLCodepoint(prev)) return ECharDir::RTL;
if (IsStrongLTR(prev)) return ECharDir::LTR;
}
}
// If we can't determine, treat as neutral
return ECharDir::Neutral;
}
// Spaces should attach to adjacent strong characters to avoid fragmentation
// This fixes "english + arabic" by keeping " + " with "english"
if (ch == L' ' || ch == L'\t')
{
if (HasStrongLTRNeighbor(s, n, i))
return ECharDir::LTR;
// Note: We don't check for RTL neighbor because ResolveNeutralDir handles that
}
// Name-token punctuation: if adjacent to LTR, treat as LTR to keep token intact
if (IsNameTokenPunct(ch) && HasStrongLTRNeighbor(s, n, i))
return ECharDir::LTR;
return ECharDir::Neutral;
}
// Pre-computed strong character lookup for O(1) neutral resolution
struct TStrongDirCache
{
std::vector<EBidiDir> nextStrong; // nextStrong[i] = direction of next strong char after position i
EBidiDir baseDir;
TStrongDirCache(const wchar_t* s, int n, EBidiDir base) : nextStrong(n), baseDir(base)
{
// Build reverse lookup: scan from end to beginning
// Use GetCharDirSmart for context-aware character classification
EBidiDir lastSeen = baseDir;
for (int i = n - 1; i >= 0; --i)
{
ECharDir cd = GetCharDirSmart(s, n, i);
if (cd == ECharDir::LTR)
lastSeen = EBidiDir::LTR;
else if (cd == ECharDir::RTL)
lastSeen = EBidiDir::RTL;
nextStrong[i] = lastSeen;
}
}
EBidiDir GetNextStrong(int i) const
{
if (i + 1 < (int)nextStrong.size())
return nextStrong[i + 1];
return baseDir;
}
};
static inline EBidiDir ResolveNeutralDir(const wchar_t* s, int n, int i, EBidiDir baseDir, EBidiDir lastStrong, const TStrongDirCache* cache = nullptr)
{
// Use pre-computed cache if available (O(1) instead of O(n))
EBidiDir nextStrong = baseDir;
if (cache)
{
nextStrong = cache->GetNextStrong(i);
}
else
{
// Linear scan (slower, but works without cache)
for (int j = i + 1; j < n; ++j)
{
ECharDir cd = GetCharDirSmart(s, n, j);
if (cd == ECharDir::LTR) { nextStrong = EBidiDir::LTR; break; }
if (cd == ECharDir::RTL) { nextStrong = EBidiDir::RTL; break; }
}
}
// If both sides agree, neutral adopts that direction
if (lastStrong == nextStrong)
return lastStrong;
// Handle edge cases for leading/trailing punctuation
if (nextStrong == baseDir && lastStrong != baseDir)
return lastStrong;
if (lastStrong == baseDir && nextStrong != baseDir)
return nextStrong;
// Otherwise fall back to base direction
return baseDir;
}
static EBidiDir DetectBaseDir_FirstStrong(const wchar_t* s, int n)
{
if (!s || n <= 0)
return EBidiDir::LTR;
for (int i = 0; i < n; ++i)
{
const wchar_t ch = s[i];
// Check RTL first, then alpha
if (IsRTLCodepoint(ch))
return EBidiDir::RTL;
if (IsStrongAlpha(ch))
return EBidiDir::LTR;
}
return EBidiDir::LTR;
}
static std::vector<wchar_t> BuildVisualBidiText_Tagless(const wchar_t* s, int n, bool forceRTL)
{
if (!s || n <= 0)
return {};
// 1) base direction
EBidiDir base = forceRTL ? EBidiDir::RTL : DetectBaseDir_FirstStrong(s, n);
// Pre-compute strong character positions for O(1) neutral resolution
TStrongDirCache strongCache(s, n, base);
// 2) split into runs
// Estimate runs based on text length (~1 per 50 chars, min 4)
std::vector<TBidiRun> runs;
const size_t estimatedRuns = (size_t)std::max(4, n / 50);
runs.reserve(estimatedRuns);
auto push_run = [&](EBidiDir d)
{
if (runs.empty() || runs.back().dir != d)
runs.push_back(TBidiRun{ d, {} });
};
// start with base so leading neutrals attach predictably
push_run(base);
EBidiDir lastStrong = base;
for (int i = 0; i < n; ++i)
{
wchar_t ch = s[i];
EBidiDir d;
ECharDir cd = GetCharDirSmart(s, n, i);
if (cd == ECharDir::RTL)
{
d = EBidiDir::RTL;
lastStrong = EBidiDir::RTL;
}
else if (cd == ECharDir::LTR)
{
d = EBidiDir::LTR;
lastStrong = EBidiDir::LTR;
}
else
{
// Pass cache for O(1) lookup instead of O(n) scan
d = ResolveNeutralDir(s, n, i, base, lastStrong, &strongCache);
}
#ifdef DEBUG_BIDI
if (i < 50) // Only log first 50 chars to avoid spam
{
BIDI_LOG("Char[%d] U+%04X '%lc' → CharDir=%s, RunDir=%s",
i, (unsigned int)ch, (ch >= 32 && ch < 127) ? ch : L'?',
cd == ECharDir::RTL ? "RTL" : (cd == ECharDir::LTR ? "LTR" : "Neutral"),
d == EBidiDir::RTL ? "RTL" : "LTR");
}
#endif
push_run(d);
runs.back().text.push_back(ch);
}
// 3) shape RTL runs in logical order (Arabic shaping)
for (auto& r : runs)
{
if (r.dir != EBidiDir::RTL)
continue;
if (r.text.empty())
continue;
// Check for potential integer overflow before allocation
if (r.text.size() > SIZE_MAX / ARABIC_SHAPING_EXPANSION_FACTOR_RETRY - ARABIC_SHAPING_SAFETY_MARGIN_RETRY)
{
BIDI_LOG("BuildVisualBidiText: RTL run too large for shaping (%zu chars)", r.text.size());
continue; // Text too large to process safely
}
std::vector<wchar_t> shaped(r.text.size() * ARABIC_SHAPING_EXPANSION_FACTOR + ARABIC_SHAPING_SAFETY_MARGIN, 0);
int outLen = Arabic_MakeShape(r.text.data(), (int)r.text.size(), shaped.data(), (int)shaped.size());
if (outLen <= 0)
{
BIDI_LOG("Arabic_MakeShape FAILED for RTL run of %zu characters", r.text.size());
BIDI_LOG(" WARNING: This RTL text segment will NOT be displayed!");
BIDI_LOG(" First few characters: U+%04X U+%04X U+%04X U+%04X",
r.text.size() > 0 ? (unsigned int)r.text[0] : 0,
r.text.size() > 1 ? (unsigned int)r.text[1] : 0,
r.text.size() > 2 ? (unsigned int)r.text[2] : 0,
r.text.size() > 3 ? (unsigned int)r.text[3] : 0);
continue;
}
// Retry once if buffer too small
if (outLen >= (int)shaped.size())
{
shaped.assign(r.text.size() * ARABIC_SHAPING_EXPANSION_FACTOR_RETRY + ARABIC_SHAPING_SAFETY_MARGIN_RETRY, 0);
outLen = Arabic_MakeShape(r.text.data(), (int)r.text.size(), shaped.data(), (int)shaped.size());
if (outLen <= 0)
continue;
// Add error check instead of silent truncation
if (outLen > (int)shaped.size())
{
BIDI_LOG("Arabic_MakeShape: Buffer still too small after retry (%d > %zu)", outLen, shaped.size());
// Shaping failed critically, use unshaped text
continue;
}
}
r.text.assign(shaped.begin(), shaped.begin() + outLen);
}
// 4) produce visual order:
// - reverse RTL runs internally
// - reverse run sequence if base RTL
std::vector<wchar_t> visual;
visual.reserve((size_t)n);
auto emit_run = [&](const TBidiRun& r)
{
if (r.dir == EBidiDir::RTL)
{
for (int k = (int)r.text.size() - 1; k >= 0; --k)
visual.push_back(r.text[(size_t)k]);
}
else
{
visual.insert(visual.end(), r.text.begin(), r.text.end());
}
};
if (base == EBidiDir::LTR)
{
for (const auto& r : runs)
emit_run(r);
}
else
{
for (int i = (int)runs.size() - 1; i >= 0; --i)
emit_run(runs[(size_t)i]);
}
return visual;
}
// ============================================================================
// Chat Message BiDi Processing (Separate name/message handling)
// ============================================================================
// Build visual BiDi text for chat messages with separate name and message
// This avoids fragile " : " detection and handles cases where username contains " : "
//
// RECOMMENDED USAGE:
// Instead of: SetValue("PlayerName : Message")
// Use this function with separated components:
// - name: "PlayerName" (without " : ")
// - msg: "Message" (without " : ")
//
// INTEGRATION NOTES:
// To use this properly, you need to:
// 1. Modify the server/network code to send chat name and message separately
// 2. Or parse the chat string in PythonNetworkStreamPhaseGame.cpp BEFORE passing to GrpTextInstance
// 3. Then call this function instead of BuildVisualBidiText_Tagless
//
static inline std::vector<wchar_t> BuildVisualChatMessage(
const wchar_t* name, int nameLen,
const wchar_t* msg, int msgLen,
bool forceRTL)
{
if (!name || !msg || nameLen <= 0 || msgLen <= 0)
return {};
// Check if message contains RTL or hyperlink tags
bool msgHasRTL = false;
bool msgHasTags = false;
for (int i = 0; i < msgLen; ++i)
{
if (IsRTLCodepoint(msg[i]))
msgHasRTL = true;
if (msg[i] == L'|')
msgHasTags = true;
if (msgHasRTL && msgHasTags)
break;
}
// Build result based on UI direction (pre-reserve exact size)
std::vector<wchar_t> visual;
visual.reserve((size_t)(nameLen + msgLen + 3)); // +3 for " : "
// Decision: UI direction determines order (for visual consistency)
// RTL UI: "Message : Name" (message on right, consistent with RTL reading flow)
// LTR UI: "Name : Message" (name on left, consistent with LTR reading flow)
if (forceRTL)
{
// RTL UI: "Message : Name"
// Don't apply BiDi if message has tags (hyperlinks are pre-formatted)
if (msgHasTags)
{
visual.insert(visual.end(), msg, msg + msgLen);
}
else
{
// Apply BiDi to message with auto-detection (don't force RTL)
// Let the BiDi algorithm detect base direction from first strong character
std::vector<wchar_t> msgVisual = BuildVisualBidiText_Tagless(msg, msgLen, false);
visual.insert(visual.end(), msgVisual.begin(), msgVisual.end());
}
visual.push_back(L' ');
visual.push_back(L':');
visual.push_back(L' ');
visual.insert(visual.end(), name, name + nameLen); // Name on left side
}
else
{
// LTR UI: "Name : Message"
visual.insert(visual.end(), name, name + nameLen); // Name on left side
visual.push_back(L' ');
visual.push_back(L':');
visual.push_back(L' ');
// Don't apply BiDi if message has tags (hyperlinks are pre-formatted)
if (msgHasTags)
{
visual.insert(visual.end(), msg, msg + msgLen);
}
else
{
// Apply BiDi to message with auto-detection (don't force RTL)
// Let the BiDi algorithm detect base direction from first strong character
std::vector<wchar_t> msgVisual = BuildVisualBidiText_Tagless(msg, msgLen, false);
visual.insert(visual.end(), msgVisual.begin(), msgVisual.end());
}
}
return visual;
}
// ============================================================================
// TextTail formatting for RTL UI
// ============================================================================
enum class EPlaceDir
{
Left, // place block to the LEFT of the cursor (cursor is a right edge)
Right // place block to the RIGHT of the cursor (cursor is a left edge)
};
template <typename TText>
inline float TextTailBiDi(TText* t, float cursorX, float y, float z, float fxAdd, EPlaceDir dir)
{
if (!t)
return cursorX;
int w = 0, h = 0;
t->GetTextSize(&w, &h);
const float fw = static_cast<float>(w);
float x;
if (dir == EPlaceDir::Left)
{
x = t->IsRTL() ? cursorX : (cursorX - fw);
// advance cursor left
cursorX = cursorX - fw - fxAdd;
}
else
{
x = t->IsRTL() ? (cursorX + fw) : cursorX;
// advance cursor right
cursorX = cursorX + fw + fxAdd;
}
// SNAP to pixel grid to avoid "broken pixels"
x = floorf(x + 0.5f);
y = floorf(y + 0.5f);
t->SetPosition(x, y, z);
t->Update();
return cursorX;
}

View File

@@ -1,5 +1,6 @@
add_subdirectory(DirectX) add_subdirectory(DirectX)
add_subdirectory(Granny) add_subdirectory(Granny)
add_subdirectory(MilesSoundSystem)
add_subdirectory(Python) add_subdirectory(Python)
add_subdirectory(SpeedTree) add_subdirectory(SpeedTree)
add_subdirectory(WebView) add_subdirectory(WebView)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,6 @@
add_library(MilesSoundSystem STATIC IMPORTED GLOBAL)
set_target_properties(MilesSoundSystem PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}/extern/include"
IMPORTED_LOCATION "${CMAKE_CURRENT_LIST_DIR}/mss64.lib"
)

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:ea999a3c3f5e22bea81b4f2658dfbe074fa1c63d3073de789735fc383cbe0f05
size 3145894

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,10 +0,0 @@
file(GLOB_RECURSE FILE_SOURCES "*.h" "*.c" "*.cpp")
add_library(AudioLib STATIC ${FILE_SOURCES})
target_link_libraries(AudioLib
cryptopp-static
mio
)
GroupSourcesByFolder(AudioLib)

View File

@@ -1,177 +0,0 @@
#include "stdafx.h"
#include "MaSoundInstance.h"
#include <miniaudio.c>
bool MaSoundInstance::InitFromBuffer(ma_engine& engine, const std::vector<uint8_t>& buffer, const std::string& identity)
{
if (!m_Initialized)
{
ma_decoder_config decoderConfig = ma_decoder_config_init_default();
ma_result result = ma_decoder_init_memory(buffer.data(), buffer.size(),
&decoderConfig, &m_Decoder);
if (!MD_ASSERT(result == MA_SUCCESS))
{
TraceError("Failed to initialize decoder memory.");
return false;
}
ma_sound_config soundConfig = ma_sound_config_init();
soundConfig.pDataSource = &m_Decoder;
result = ma_sound_init_ex(&engine, &soundConfig, &m_Sound);
if (!MD_ASSERT(result == MA_SUCCESS))
{
TraceError("Failed to initialize sound.");
return false;
}
m_Identity = identity;
m_Initialized = true;
}
return m_Initialized;
}
// Basically c&p
bool MaSoundInstance::InitFromFile(ma_engine& engine, const std::string& filePathOnDisk)
{
if (!m_Initialized)
{
ma_decoder_config decoderConfig = ma_decoder_config_init_default();
ma_result result = ma_decoder_init_file(filePathOnDisk.c_str(), &decoderConfig, &m_Decoder);
if (!MD_ASSERT(result == MA_SUCCESS))
{
TraceError("Failed to initialize sound file decoder.");
return false;
}
ma_sound_config soundConfig = ma_sound_config_init();
soundConfig.pDataSource = &m_Decoder;
result = ma_sound_init_ex(&engine, &soundConfig, &m_Sound);
if (!MD_ASSERT(result == MA_SUCCESS))
{
TraceError("Failed to initialize sound.");
return false;
}
m_Identity = filePathOnDisk;
m_Initialized = true;
}
return m_Initialized;
}
void MaSoundInstance::Destroy()
{
if (m_Initialized)
{
ma_sound_uninit(&m_Sound);
ma_decoder_uninit(&m_Decoder);
}
m_Initialized = false;
m_Identity = "";
m_FadeTargetVolume = 0.0f;
m_FadeRatePerFrame = 0.0f;
}
bool MaSoundInstance::IsInitialized() const
{
return m_Initialized;
}
bool MaSoundInstance::IsPlaying() const
{
return ma_sound_is_playing(&m_Sound) == MA_TRUE;
}
bool MaSoundInstance::Play()
{
return m_Initialized && ma_sound_seek_to_pcm_frame(&m_Sound, 0) == MA_SUCCESS && ma_sound_start(&m_Sound) == MA_SUCCESS;
}
bool MaSoundInstance::Resume()
{
return m_Initialized && ma_sound_start(&m_Sound) == MA_SUCCESS;
}
bool MaSoundInstance::Stop()
{
return m_Initialized && ma_sound_stop(&m_Sound) == MA_SUCCESS;
}
void MaSoundInstance::Loop()
{
ma_sound_set_looping(&m_Sound, MA_TRUE);
}
float MaSoundInstance::GetVolume() const
{
return ma_sound_get_volume(&m_Sound);
}
void MaSoundInstance::SetVolume(float volume)
{
ma_sound_set_volume(&m_Sound, volume);
}
void MaSoundInstance::SetPitch(float pitch)
{
ma_sound_set_pitch(&m_Sound, pitch);
}
void MaSoundInstance::SetPosition(float x, float y, float z)
{
ma_sound_set_position(&m_Sound, x, y, z);
}
const std::string& MaSoundInstance::GetIdentity() const
{
return m_Identity;
}
void MaSoundInstance::Config3D(bool toggle, float minDist, float maxDist)
{
ma_sound_set_spatialization_enabled(&m_Sound, toggle);
ma_sound_set_rolloff(&m_Sound, 1.0f);
ma_sound_set_min_distance(&m_Sound, minDist);
ma_sound_set_max_distance(&m_Sound, maxDist);
ma_sound_set_attenuation_model(&m_Sound, ma_attenuation_model_linear);
}
void MaSoundInstance::Fade(float toVolume, float secDurationFromMinMax)
{
m_FadeTargetVolume = std::clamp<float>(toVolume, 0.0f, 1.0f);
if (m_FadeTargetVolume != GetVolume())
{
const float rate = 1.0f / CS_CLIENT_FPS / secDurationFromMinMax;
m_FadeRatePerFrame = GetVolume() > m_FadeTargetVolume ? -rate : rate;
}
}
void MaSoundInstance::StopFading()
{
m_FadeRatePerFrame = 0.0f;
m_FadeTargetVolume = 0.0f;
}
bool MaSoundInstance::IsFading() const
{
return m_FadeRatePerFrame != 0.0f;
}
void MaSoundInstance::Update()
{
if (m_FadeRatePerFrame != 0.0f)
{
float targetVolume = std::clamp<float>(m_FadeTargetVolume, 0.0f, 1.0f);
float volume = std::clamp<float>(GetVolume() + m_FadeRatePerFrame, 0.0f, 1.0f);
if ((m_FadeRatePerFrame > 0.0f && volume >= targetVolume) || (m_FadeRatePerFrame < 0.0f && volume <= targetVolume))
{
volume = m_FadeTargetVolume;
m_FadeRatePerFrame = 0.0f;
if (m_FadeTargetVolume <= 0.0f)
ma_sound_stop(&m_Sound);
}
ma_sound_set_volume(&m_Sound, volume);
}
}

View File

@@ -1,57 +0,0 @@
#pragma once
#define MA_NO_WASAPI
#define MA_ENABLE_DSOUND
#define MA_ENABLE_WINMM
#include <miniaudio.h>
inline constexpr float CS_CLIENT_FPS = 61.0f;
class MaSoundInstance
{
public:
bool InitFromBuffer(ma_engine& engine, const std::vector<uint8_t>& buffer, const std::string& identity);
bool InitFromFile(ma_engine& engine, const std::string& filePathOnDisk);
void Destroy();
bool IsInitialized() const;
bool IsPlaying() const;
bool Play();
bool Resume();
bool Stop();
void Loop();
float GetVolume() const;
void SetVolume(float volume);
void SetPitch(float pitch);
void SetPosition(float x, float y, float z);
const std::string& GetIdentity() const;
void Config3D(bool toggle, float minDist = 100.0f/*1m*/, float maxDist = 4000.0f/*40m*/);
void Fade(float toVolume, float secDurationFromMinMax);
void StopFading();
bool IsFading() const;
void Update();
private:
std::string m_Identity;
ma_sound m_Sound{};
ma_decoder m_Decoder{};
bool m_Initialized{};
float m_FadeTargetVolume{};
float m_FadeRatePerFrame{};
};

View File

@@ -1,258 +0,0 @@
#include "stdafx.h"
#include "SoundEngine.h"
#include "EterBase/Random.h"
#include "EterBase/Timer.h"
#include "PackLib/PackManager.h"
SoundEngine::SoundEngine()
{
}
SoundEngine::~SoundEngine()
{
for (auto& [name, instance] : m_Sounds2D)
instance.Destroy();
for (auto& instance : m_Sounds3D)
instance.Destroy();
ma_engine_uninit(&m_Engine);
m_Files.clear();
m_Sounds2D.clear();
}
bool SoundEngine::Initialize()
{
if (!MD_ASSERT(ma_engine_init(NULL, &m_Engine) == MA_SUCCESS))
{
TraceError("SoundEngine::Initialize: Failed to initialize engine.");
return false;
}
ma_engine_listener_set_position(&m_Engine, 0, 0, 0, 0); // engine
SetListenerPosition(0.0f, 0.0f, 0.0f); // character
SetListenerOrientation(0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f);
return true;
}
void SoundEngine::SetSoundVolume(float volume)
{
m_SoundVolume = std::clamp<float>(volume, 0.0, 1.0);
}
bool SoundEngine::PlaySound2D(const std::string& name)
{
if (!Internal_LoadSoundFromPack(name))
return false;
auto& instance = m_Sounds2D[name]; // 2d sounds are persistent, no need to destroy
instance.InitFromBuffer(m_Engine, m_Files[name], name);
instance.Config3D(false);
instance.SetVolume(m_SoundVolume);
return instance.Play();
}
MaSoundInstance* SoundEngine::PlaySound3D(const std::string& name, float fx, float fy, float fz)
{
if (auto instance = Internal_GetInstance3D(name))
{
constexpr float minDist = 100.0f; // 1m
constexpr float maxDist = 5000.0f; // 50m
instance->SetPosition(fx - m_CharacterPosition.x,
fy - m_CharacterPosition.y,
fz - m_CharacterPosition.z);
instance->Config3D(true, minDist, maxDist);
instance->SetVolume(m_SoundVolume);
instance->Play();
return instance;
}
return nullptr;
}
MaSoundInstance* SoundEngine::PlayAmbienceSound3D(float fx, float fy, float fz, const std::string& name, int loopCount)
{
auto vec3 = ma_engine_listener_get_position(&m_Engine, 0);
float dx = fx - vec3.x;
float dy = fy - vec3.y;
float dz = fz - vec3.z;
float distance = sqrtf(dx * dx + dy * dy + dz * dz);
return PlaySound3D(name, fx, fy, fz);
}
void SoundEngine::StopAllSound3D()
{
for (auto& instance : m_Sounds3D)
instance.Stop();
}
void SoundEngine::UpdateSoundInstance(float fx, float fy, float fz, uint32_t dwcurFrame, const NSound::TSoundInstanceVector* c_pSoundInstanceVector, bool checkFrequency)
{
for (uint32_t i = 0; i < c_pSoundInstanceVector->size(); ++i)
{
const NSound::TSoundInstance& c_rSoundInstance = c_pSoundInstanceVector->at(i);
if (c_rSoundInstance.dwFrame == dwcurFrame)
{
if (checkFrequency)
{
float& lastPlay = m_PlaySoundHistoryMap[c_rSoundInstance.strSoundFileName];
float diff = CTimer::Instance().GetCurrentSecond() - lastPlay;
if (CTimer::Instance().GetCurrentSecond() - lastPlay < 0.3f)
return;
lastPlay = CTimer::Instance().GetCurrentSecond();
}
PlaySound3D(c_rSoundInstance.strSoundFileName, fx, fy, fz);
}
}
}
bool SoundEngine::FadeInMusic(const std::string& path, float targetVolume /* 1.0f by default */, float fadeInDurationSecondsFromMin)
{
if (path.empty())
return false;
auto& fadeOutMusic = m_Music[m_CurrentMusicIndex];
if (fadeOutMusic.IsPlaying() && path == fadeOutMusic.GetIdentity())
{
fadeOutMusic.Fade(targetVolume, fadeInDurationSecondsFromMin);
return fadeOutMusic.Resume();
}
// We're basically just swapping
FadeOutMusic(fadeOutMusic.GetIdentity());
m_CurrentMusicIndex = int(!m_CurrentMusicIndex);
auto& music = m_Music[m_CurrentMusicIndex];
music.Destroy();
music.InitFromFile(m_Engine, path);
music.Config3D(false);
music.Loop();
music.SetVolume(0.0f);
music.Fade(targetVolume, fadeInDurationSecondsFromMin);
return music.Play();
}
void SoundEngine::FadeOutMusic(const std::string& name, float targetVolume, float fadeOutDurationSecondsFromMax)
{
for (auto& music : m_Music)
{
if (music.GetIdentity() == name)
music.Fade(targetVolume, fadeOutDurationSecondsFromMax);
}
}
void SoundEngine::FadeOutAllMusic()
{
for (auto& music : m_Music)
FadeOutMusic(music.GetIdentity());
}
void SoundEngine::SetMusicVolume(float volume)
{
m_MusicVolume = std::clamp<float>(volume, 0.0f, 1.0f);
m_Music[m_CurrentMusicIndex].StopFading();
m_Music[m_CurrentMusicIndex].SetVolume(m_MusicVolume);
}
float SoundEngine::GetMusicVolume() const
{
return m_MusicVolume;
}
void SoundEngine::SaveVolume(bool isMinimized)
{
constexpr float ratePerSecond = 1.0f / CS_CLIENT_FPS;
// 1.0 to 0 in 1s if minimized, 3s if just out of focus
const float durationOnFullVolume = isMinimized ? 1.0f : 3.0f;
float outOfFocusVolume = 0.35f;
if (m_MasterVolume <= outOfFocusVolume)
outOfFocusVolume = m_MasterVolume;
m_MasterVolumeFadeTarget = isMinimized ? 0.0f : outOfFocusVolume;
m_MasterVolumeFadeRatePerFrame = -ratePerSecond / durationOnFullVolume;
}
void SoundEngine::RestoreVolume()
{
constexpr float ratePerSecond = 1.0f / CS_CLIENT_FPS;
constexpr float durationToFullVolume = 4.0f; // 0 to 1.0 in 4s
m_MasterVolumeFadeTarget = m_MasterVolume;
m_MasterVolumeFadeRatePerFrame = ratePerSecond / durationToFullVolume;
}
void SoundEngine::SetMasterVolume(float volume)
{
m_MasterVolume = volume;
ma_engine_set_volume(&m_Engine, volume);
}
void SoundEngine::SetListenerPosition(float x, float y, float z)
{
m_CharacterPosition.x = x;
m_CharacterPosition.y = y;
m_CharacterPosition.z = z;
}
void SoundEngine::SetListenerOrientation(float forwardX, float forwardY, float forwardZ,
float upX, float upY, float upZ)
{
ma_engine_listener_set_direction(&m_Engine, 0, forwardX, forwardY, -forwardZ);
ma_engine_listener_set_world_up(&m_Engine, 0, upX, -upY, upZ);
}
void SoundEngine::Update()
{
for (auto& music : m_Music)
music.Update();
if (m_MasterVolumeFadeRatePerFrame)
{
float volume = ma_engine_get_volume(&m_Engine) + m_MasterVolumeFadeRatePerFrame;
if ((m_MasterVolumeFadeRatePerFrame > 0.0f && volume >= m_MasterVolumeFadeTarget) || (m_MasterVolumeFadeRatePerFrame < 0.0f && volume <= m_MasterVolumeFadeTarget))
{
volume = m_MasterVolumeFadeTarget;
m_MasterVolumeFadeRatePerFrame = 0.0f;
}
ma_engine_set_volume(&m_Engine, volume);
}
}
MaSoundInstance* SoundEngine::Internal_GetInstance3D(const std::string& name)
{
if (Internal_LoadSoundFromPack(name))
{
for (auto& instance : m_Sounds3D)
{
if (!instance.IsPlaying())
{
instance.Destroy();
instance.InitFromBuffer(m_Engine, m_Files[name], name);
return &instance;
}
}
}
return nullptr;
}
bool SoundEngine::Internal_LoadSoundFromPack(const std::string& name)
{
if (m_Files.find(name) == m_Files.end())
{
TPackFile soundFile;
if (!CPackManager::Instance().GetFile(name, soundFile))
{
TraceError("Internal_LoadSoundFromPack: SoundEngine: Failed to register file '%s' - not found.", name.c_str());
return false;
}
auto& buffer = m_Files[name];
buffer.resize(soundFile.size());
memcpy(buffer.data(), soundFile.data(), soundFile.size());
}
return true;
}

View File

@@ -1,98 +0,0 @@
#pragma once
#include "EterBase/Singleton.h"
#include "Type.h"
#include "MaSoundInstance.h"
//#include <miniaudio.h>
#include <array>
#include <unordered_map>
struct SoundFile
{
std::string name;
std::vector<std::byte> buffer; // raw file data.
};
class SoundEngine : public CSingleton<SoundEngine>
{
public:
enum ESoundConfig
{
SOUND_INSTANCE_3D_MAX_NUM = 32,
};
// enum ESoundType
// {
// SOUND_TYPE_INTERFACE, // Interface sounds. Loaded on game opening, unloaded when the game ends.
// SOUND_TYPE_CHARACTER, // Character sounds(hit, damage, etc). Loaded on login, unloaded when the game ends.
// SOUND_TYPE_MONSTER, // monster attacks, hits, etc. Loaded and unloaded on warp
// SOUND_TYPE_AMBIENCE, // Wind, rain, birds, etc. Loaded and unloaded on warp
// SOUND_TYPE_MUSIC, // Bg music played on demand
// SOUND_TYPE_MAX_NUM,
// };
public:
SoundEngine();
~SoundEngine();
bool Initialize();
void SetSoundVolume(float volume);
bool PlaySound2D(const std::string& name);
MaSoundInstance* PlaySound3D(const std::string& name, float fx, float fy, float fz);
MaSoundInstance* PlayAmbienceSound3D(float fx, float fy, float fz, const std::string& name, int loopCount = 1);
void StopAllSound3D();
void UpdateSoundInstance(float fx, float fy, float fz, uint32_t dwcurFrame, const NSound::TSoundInstanceVector* c_pSoundInstanceVector, bool checkFrequency = false);
bool FadeInMusic(const std::string& path, float targetVolume = 1.0f, float fadeInDurationSecondsFromMin = 1.5f);
void FadeOutMusic(const std::string& name, float targetVolume = 0.0f, float fadeOutDurationSecondsFromMax = 1.5f);
void FadeOutAllMusic();
void SetMusicVolume(float volume);
float GetMusicVolume() const;
void SaveVolume(bool isMinimized);
void RestoreVolume();
void SetMasterVolume(float volume);
void SetListenerPosition(float x, float y, float z);
void SetListenerOrientation(float forwardX, float forwardY, float forwardZ,
float upX, float upY, float upZ);
void Update();
private:
MaSoundInstance* Internal_GetInstance3D(const std::string& name);
bool Internal_LoadSoundFromPack(const std::string& name);
private:
struct { float x, y, z; } m_CharacterPosition{};
ma_engine m_Engine{};
std::unordered_map<std::string, std::vector<uint8_t>> m_Files;
std::unordered_map<std::string, MaSoundInstance> m_Sounds2D;
std::array<MaSoundInstance, SOUND_INSTANCE_3D_MAX_NUM> m_Sounds3D;
std::unordered_map<std::string, float> m_PlaySoundHistoryMap;
// One song at a time, but holding both current and previous for graceful fading
std::array<MaSoundInstance, 2> m_Music;
int m_CurrentMusicIndex{};
float m_MusicVolume{ 1.0f };
float m_SoundVolume{ 1.0f };
float m_MasterVolume{ 1.0f };
float m_MasterVolumeFadeTarget{};
float m_MasterVolumeFadeRatePerFrame{};
};

View File

@@ -1,9 +0,0 @@
#pragma once
//#include <windows.h>
#include "EterBase/CRC32.h"
#include "EterBase/Utils.h"
#include "EterBase/Debug.h"
#include <algorithm>

View File

@@ -1,141 +0,0 @@
#include "StdAfx.h"
#include "Type.h"
#include "EterLib/TextFileLoader.h"
#include <utf8.h>
std::string NSound::strResult;
const char* NSound::GetResultString()
{
return strResult.c_str();
}
void NSound::SetResultString(const char* c_pszStr)
{
strResult.assign(c_pszStr);
}
bool NSound::LoadSoundInformationPiece(const char* c_szFileName, NSound::TSoundDataVector& rSoundDataVector, const char* c_szPathHeader)
{
std::string strResult;
strResult = c_szFileName;
CTextFileLoader* pkTextFileLoader = CTextFileLoader::Cache(c_szFileName);
if (!pkTextFileLoader)
return false;
CTextFileLoader& rkTextFileLoader = *pkTextFileLoader;
if (rkTextFileLoader.IsEmpty())
{
SetResultString((strResult + " Can not open file for reading").c_str());
return false;
}
rkTextFileLoader.SetTop();
int iCount;
if (!rkTextFileLoader.GetTokenInteger("sounddatacount", &iCount))
{
SetResultString((strResult + " File format error, SoundDataCount Unable to find.").c_str());
return false;
}
rSoundDataVector.clear();
rSoundDataVector.resize(iCount);
char szSoundDataHeader[32 + 1];
for (uint32_t i = 0; i < rSoundDataVector.size(); ++i)
{
_snprintf_s(szSoundDataHeader, sizeof(szSoundDataHeader), "sounddata%02d", i);
CTokenVector* pTokenVector;
if (!rkTextFileLoader.GetTokenVector(szSoundDataHeader, &pTokenVector))
{
SetResultString((strResult + " File format error: " + szSoundDataHeader + " Unable to find").c_str());
return false;
}
if (2 != pTokenVector->size())
{
SetResultString((strResult + " File format error: The size of the vector is not 2").c_str());
return false;
}
rSoundDataVector[i].fTime = (float)atof(pTokenVector->at(0).c_str());
if (c_szPathHeader)
{
rSoundDataVector[i].strSoundFileName = c_szPathHeader;
rSoundDataVector[i].strSoundFileName += pTokenVector->at(1).c_str();
}
else
{
rSoundDataVector[i].strSoundFileName = pTokenVector->at(1).c_str();
}
//TraceError("LoadSoundInformation %s -- %f -- %s", c_szFileName, rSoundDataVector[i].fTime, rSoundDataVector[i].strSoundFileName.c_str());
}
SetResultString((strResult + " Loaded").c_str());
return true;
}
bool NSound::SaveSoundInformationPiece(const char* c_szFileName, NSound::TSoundDataVector& rSoundDataVector)
{
if (rSoundDataVector.empty()) // If no data is considered success
{
if (IsFile(c_szFileName)) // If the data is empty but there is a file
{
_unlink(c_szFileName); // erase.
}
return true;
}
std::string strResult;
strResult = c_szFileName;
// UTF-8 → UTF-16 conversion for Unicode path support
std::wstring wFileName = Utf8ToWide(c_szFileName);
FILE* File = _wfopen(wFileName.c_str(), L"wt");
if (!File)
{
char szErrorText[256 + 1];
_snprintf_s(szErrorText, sizeof(szErrorText), "Failed to save file (%s).\nPlease check if it is read-only or you have no space on the disk.\n", c_szFileName);
LogBox(szErrorText, "Error");
SetResultString((strResult + " Cannot open file for writing").c_str());
return false;
}
fprintf(File, "ScriptType CharacterSoundInformation\n");
fprintf(File, "\n");
fprintf(File, "SoundDataCount %llu\n", rSoundDataVector.size());
for (uint32_t i = 0; i < rSoundDataVector.size(); ++i)
{
NSound::TSoundData& rSoundData = rSoundDataVector[i];
fprintf(File, "SoundData%02d %f \"%s\"\n", i, rSoundData.fTime, rSoundData.strSoundFileName.c_str());
}
fclose(File);
return true;
}
void NSound::DataToInstance(const TSoundDataVector& c_rSoundDataVector, TSoundInstanceVector* pSoundInstanceVector)
{
if (c_rSoundDataVector.empty())
return;
uint32_t dwFPS = 60;
const float c_fFrameTime = 1.0f / float(dwFPS);
pSoundInstanceVector->clear();
pSoundInstanceVector->resize(c_rSoundDataVector.size());
for (uint32_t i = 0; i < c_rSoundDataVector.size(); ++i)
{
const TSoundData& c_rSoundData = c_rSoundDataVector[i];
TSoundInstance& rSoundInstance = pSoundInstanceVector->at(i);
rSoundInstance.dwFrame = (uint32_t)(c_rSoundData.fTime / c_fFrameTime);
rSoundInstance.strSoundFileName = c_rSoundData.strSoundFileName;
}
}

View File

@@ -1,29 +0,0 @@
#pragma once
#include <vector>
#include <string>
namespace NSound
{
extern std::string strResult;
typedef struct SSoundData
{
float fTime;
std::string strSoundFileName;
} TSoundData;
typedef struct SSoundInstance
{
uint32_t dwFrame;
std::string strSoundFileName;
} TSoundInstance;
typedef std::vector<TSoundData> TSoundDataVector;
typedef std::vector<TSoundInstance> TSoundInstanceVector;
bool LoadSoundInformationPiece(const char* c_szFileName, TSoundDataVector& rSoundDataVector, const char* c_szPathHeader = NULL);
bool SaveSoundInformationPiece(const char* c_szFileName, TSoundDataVector& rSoundDataVector);
void DataToInstance(const TSoundDataVector& c_rSoundDataVector, TSoundInstanceVector* pSoundInstanceVector);
const char* GetResultString();
void SetResultString(const char* c_pszStr);
};

View File

@@ -1,4 +1,3 @@
add_subdirectory(AudioLib)
add_subdirectory(Discord) add_subdirectory(Discord)
add_subdirectory(EffectLib) add_subdirectory(EffectLib)
add_subdirectory(EterBase) add_subdirectory(EterBase)
@@ -6,12 +5,12 @@ add_subdirectory(EterGrnLib)
add_subdirectory(EterImageLib) add_subdirectory(EterImageLib)
add_subdirectory(EterLib) add_subdirectory(EterLib)
add_subdirectory(EterLocale) add_subdirectory(EterLocale)
add_subdirectory(EterPack)
add_subdirectory(EterPythonLib) add_subdirectory(EterPythonLib)
add_subdirectory(GameLib) add_subdirectory(GameLib)
add_subdirectory(MilesLib)
add_subdirectory(PRTerrainLib) add_subdirectory(PRTerrainLib)
add_subdirectory(ScriptLib) add_subdirectory(ScriptLib)
add_subdirectory(SpeedTreeLib) add_subdirectory(SpeedTreeLib)
add_subdirectory(SphereLib) add_subdirectory(SphereLib)
add_subdirectory(UserInterface) add_subdirectory(UserInterface)
add_subdirectory(PackMaker)
add_subdirectory(PackLib)

View File

@@ -1,5 +1,6 @@
#include "connection.h" #include "connection.h"
#define WIN32_LEAN_AND_MEAN
#define NOMCX #define NOMCX
#define NOSERVICE #define NOSERVICE
#define NOIME #define NOIME

View File

@@ -1,6 +1,7 @@
#include "discord_rpc.h" #include "discord_rpc.h"
#include "discord_register.h" #include "discord_register.h"
#define WIN32_LEAN_AND_MEAN
#define NOMCX #define NOMCX
#define NOSERVICE #define NOSERVICE
#define NOIME #define NOIME
@@ -133,36 +134,27 @@ static void Discord_RegisterW(const wchar_t* applicationId, const wchar_t* comma
extern "C" DISCORD_EXPORT void Discord_Register(const char* applicationId, const char* command) extern "C" DISCORD_EXPORT void Discord_Register(const char* applicationId, const char* command)
{ {
wchar_t appId[32]; wchar_t appId[32];
int app = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, applicationId, -1, appId, 32); MultiByteToWideChar(CP_UTF8, 0, applicationId, -1, appId, 32);
if (app <= 0)
return;
wchar_t openCommand[1024]; wchar_t openCommand[1024];
const wchar_t* wcommand = nullptr; const wchar_t* wcommand = nullptr;
if (command && command[0]) { if (command && command[0]) {
const auto commandBufferLen = sizeof(openCommand) / sizeof(*openCommand); const auto commandBufferLen = sizeof(openCommand) / sizeof(*openCommand);
MultiByteToWideChar(CP_UTF8, 0, command, -1, openCommand, commandBufferLen);
int ok = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, command, -1, openCommand, commandBufferLen);
if (ok <= 0)
return;
wcommand = openCommand; wcommand = openCommand;
} }
Discord_RegisterW(appId, wcommand); Discord_RegisterW(appId, wcommand);
} }
extern "C" DISCORD_EXPORT void Discord_RegisterSteamGame(const char* applicationId, const char* steamId) extern "C" DISCORD_EXPORT void Discord_RegisterSteamGame(const char* applicationId,
const char* steamId)
{ {
wchar_t appId[32]; wchar_t appId[32];
int app = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, applicationId, -1, appId, 32); MultiByteToWideChar(CP_UTF8, 0, applicationId, -1, appId, 32);
if (app <= 0)
return;
wchar_t wSteamId[32]; wchar_t wSteamId[32];
int steam = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, steamId, -1, wSteamId, 32); MultiByteToWideChar(CP_UTF8, 0, steamId, -1, wSteamId, 32);
if (steam <= 0)
return;
HKEY key; HKEY key;
auto status = RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Valve\\Steam", 0, KEY_READ, &key); auto status = RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Valve\\Steam", 0, KEY_READ, &key);

View File

@@ -3,8 +3,7 @@
add_library(EffectLib STATIC ${FILE_SOURCES}) add_library(EffectLib STATIC ${FILE_SOURCES})
target_link_libraries(EffectLib target_link_libraries(EffectLib
cryptopp-static lzo2
mio
) )
GroupSourcesByFolder(EffectLib) GroupSourcesByFolder(EffectLib)

View File

@@ -96,7 +96,7 @@ bool CEffectData::LoadScript(const char * c_szFileName)
bool CEffectData::LoadSoundScriptData(const char * c_szFileName) bool CEffectData::LoadSoundScriptData(const char * c_szFileName)
{ {
NSound::TSoundDataVector SoundDataVector; TSoundDataVector SoundDataVector;
if (LoadSoundInformationPiece(c_szFileName, SoundDataVector)) if (LoadSoundInformationPiece(c_szFileName, SoundDataVector))
{ {
@@ -164,7 +164,7 @@ CEffectMeshScript * CEffectData::GetMeshPointer(DWORD dwPosition)
return m_MeshVector[dwPosition]; return m_MeshVector[dwPosition];
} }
NSound::TSoundInstanceVector * CEffectData::GetSoundInstanceVector() TSoundInstanceVector * CEffectData::GetSoundInstanceVector()
{ {
return &m_SoundInstanceVector; return &m_SoundInstanceVector;
} }

View File

@@ -1,6 +1,6 @@
#pragma once #pragma once
#include "AudioLib/Type.h" #include "../milesLib/Type.h"
#include "ParticleSystemData.h" #include "ParticleSystemData.h"
#include "EffectMesh.h" #include "EffectMesh.h"
@@ -30,7 +30,7 @@ class CEffectData
DWORD GetLightCount(); DWORD GetLightCount();
CLightData * GetLightPointer(DWORD dwPosition); CLightData * GetLightPointer(DWORD dwPosition);
NSound::TSoundInstanceVector * GetSoundInstanceVector(); TSoundInstanceVector * GetSoundInstanceVector();
float GetBoundingSphereRadius(); float GetBoundingSphereRadius();
D3DXVECTOR3 GetBoundingSpherePosition(); D3DXVECTOR3 GetBoundingSpherePosition();
@@ -52,7 +52,7 @@ class CEffectData
TParticleVector m_ParticleVector; TParticleVector m_ParticleVector;
TMeshVector m_MeshVector; TMeshVector m_MeshVector;
TLightVector m_LightVector; TLightVector m_LightVector;
NSound::TSoundInstanceVector m_SoundInstanceVector; TSoundInstanceVector m_SoundInstanceVector;
float m_fBoundingSphereRadius; float m_fBoundingSphereRadius;
D3DXVECTOR3 m_v3BoundingSpherePosition; D3DXVECTOR3 m_v3BoundingSpherePosition;

View File

@@ -90,14 +90,6 @@ void CEffectElementBaseInstance::Destroy()
} }
CEffectElementBaseInstance::CEffectElementBaseInstance() CEffectElementBaseInstance::CEffectElementBaseInstance()
: mc_pmatLocal(nullptr)
, m_isActive(false)
, m_fLocalTime(0.0f)
, m_dwStartTime(0)
, m_fElapsedTime(0.0f)
, m_fRemainingTime(0.0f)
, m_bStart(false)
, m_pBase(nullptr)
{ {
} }
CEffectElementBaseInstance::~CEffectElementBaseInstance() CEffectElementBaseInstance::~CEffectElementBaseInstance()

View File

@@ -3,9 +3,9 @@
#include "ParticleSystemInstance.h" #include "ParticleSystemInstance.h"
#include "SimpleLightInstance.h" #include "SimpleLightInstance.h"
#include "EterBase/Stl.h" #include "../eterBase/Stl.h"
#include "EterLib/StateManager.h" #include "../eterLib/StateManager.h"
#include "AudioLib/SoundEngine.h" #include "../MilesLib/SoundManager.h"
CDynamicPool<CEffectInstance> CEffectInstance::ms_kPool; CDynamicPool<CEffectInstance> CEffectInstance::ms_kPool;
int CEffectInstance::ms_iRenderingEffectCount = 0; int CEffectInstance::ms_iRenderingEffectCount = 0;
@@ -50,12 +50,12 @@ void CEffectInstance::UpdateSound()
{ {
if (m_pSoundInstanceVector) if (m_pSoundInstanceVector)
{ {
SoundEngine::Instance().UpdateSoundInstance(m_matGlobal._41, UpdateSoundInstance(m_dwFrame,
m_matGlobal._42, *m_pSoundInstanceVector,
m_matGlobal._43, m_matGlobal._41,
m_dwFrame, m_matGlobal._42,
m_pSoundInstanceVector, m_matGlobal._43,
false); false);
// NOTE : 매트릭스에서 위치를 직접 얻어온다 - [levites] // NOTE : 매트릭스에서 위치를 직접 얻어온다 - [levites]
} }
++m_dwFrame; ++m_dwFrame;
@@ -80,7 +80,11 @@ void CEffectInstance::OnUpdate()
{ {
Transform(); Transform();
#ifdef WORLD_EDITOR
FEffectUpdator f(CTimer::Instance().GetElapsedSecond());
#else
FEffectUpdator f(CTimer::Instance().GetCurrentSecond()-m_fLastTime); FEffectUpdator f(CTimer::Instance().GetCurrentSecond()-m_fLastTime);
#endif
f = std::for_each(m_ParticleInstanceVector.begin(), m_ParticleInstanceVector.end(),f); f = std::for_each(m_ParticleInstanceVector.begin(), m_ParticleInstanceVector.end(),f);
f = std::for_each(m_MeshInstanceVector.begin(), m_MeshInstanceVector.end(),f); f = std::for_each(m_MeshInstanceVector.begin(), m_MeshInstanceVector.end(),f);
f = std::for_each(m_LightInstanceVector.begin(), m_LightInstanceVector.end(),f); f = std::for_each(m_LightInstanceVector.begin(), m_LightInstanceVector.end(),f);
@@ -91,7 +95,7 @@ void CEffectInstance::OnUpdate()
void CEffectInstance::OnRender() void CEffectInstance::OnRender()
{ {
STATEMANAGER.SetFVF(D3DFVF_XYZ | D3DFVF_TEX1); STATEMANAGER.SetFVF(D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1);
STATEMANAGER.SaveSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_NONE); STATEMANAGER.SaveSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_NONE);
STATEMANAGER.SaveSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_NONE); STATEMANAGER.SaveSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_NONE);
@@ -102,19 +106,30 @@ void CEffectInstance::OnRender()
STATEMANAGER.SaveRenderState(D3DRS_ALPHATESTENABLE, FALSE); STATEMANAGER.SaveRenderState(D3DRS_ALPHATESTENABLE, FALSE);
STATEMANAGER.SaveRenderState(D3DRS_CULLMODE, D3DCULL_NONE); STATEMANAGER.SaveRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
STATEMANAGER.SaveRenderState(D3DRS_ZWRITEENABLE, FALSE); STATEMANAGER.SaveRenderState(D3DRS_ZWRITEENABLE, FALSE);
///// STATEMANAGER.SaveRenderState(D3DRS_LIGHTING, FALSE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR); STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TEXTURE); STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR);
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_TEXTURE); STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
std::for_each(m_ParticleInstanceVector.begin(),m_ParticleInstanceVector.end(),std::mem_fn(&CEffectElementBaseInstance::Render)); std::for_each(m_ParticleInstanceVector.begin(),m_ParticleInstanceVector.end(),std::mem_fn(&CEffectElementBaseInstance::Render));
STATEMANAGER.SetFVF(D3DFVF_XYZ | D3DFVF_TEX1);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR);
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
std::for_each(m_MeshInstanceVector.begin(),m_MeshInstanceVector.end(),std::mem_fn(&CEffectElementBaseInstance::Render)); std::for_each(m_MeshInstanceVector.begin(),m_MeshInstanceVector.end(),std::mem_fn(&CEffectElementBaseInstance::Render));
/////
STATEMANAGER.RestoreSamplerState(0, D3DSAMP_MINFILTER); STATEMANAGER.RestoreSamplerState(0, D3DSAMP_MINFILTER);
STATEMANAGER.RestoreSamplerState(0, D3DSAMP_MAGFILTER); STATEMANAGER.RestoreSamplerState(0, D3DSAMP_MAGFILTER);
@@ -124,6 +139,7 @@ void CEffectInstance::OnRender()
STATEMANAGER.RestoreRenderState(D3DRS_ALPHATESTENABLE); STATEMANAGER.RestoreRenderState(D3DRS_ALPHATESTENABLE);
STATEMANAGER.RestoreRenderState(D3DRS_CULLMODE); STATEMANAGER.RestoreRenderState(D3DRS_CULLMODE);
STATEMANAGER.RestoreRenderState(D3DRS_ZWRITEENABLE); STATEMANAGER.RestoreRenderState(D3DRS_ZWRITEENABLE);
STATEMANAGER.RestoreRenderState(D3DRS_LIGHTING);
++ms_iRenderingEffectCount; ++ms_iRenderingEffectCount;
} }
@@ -267,10 +283,18 @@ void CEffectInstance::Clear()
__Initialize(); __Initialize();
} }
void CEffectInstance::BatchParticles()
{
std::for_each(m_ParticleInstanceVector.begin(), m_ParticleInstanceVector.end(), std::mem_fn(&CParticleSystemInstance::BatchParticles));
}
void CEffectInstance::RenderMeshes()
{
std::for_each(m_MeshInstanceVector.begin(), m_MeshInstanceVector.end(), std::mem_fn(&CEffectElementBaseInstance::Render));
}
void CEffectInstance::__Initialize() void CEffectInstance::__Initialize()
{ {
ReleaseAlwaysHidden();
m_isAlive = FALSE; m_isAlive = FALSE;
m_dwFrame = 0; m_dwFrame = 0;
m_pSoundInstanceVector = NULL; m_pSoundInstanceVector = NULL;

View File

@@ -1,10 +1,9 @@
#pragma once #pragma once
#include "UserInterface/Locale_inc.h"
#include "Eterlib/GrpObjectInstance.h" #include "Eterlib/GrpObjectInstance.h"
#include "Eterlib/Pool.h" #include "Eterlib/Pool.h"
#include "AudioLib/Type.h" #include "Mileslib/Type.h"
#include "StdAfx.h"
#include "EffectElementBaseInstance.h" #include "EffectElementBaseInstance.h"
#include "EffectData.h" #include "EffectData.h"
#include "EffectMeshInstance.h" #include "EffectMeshInstance.h"
@@ -42,12 +41,6 @@ class CEffectInstance : public CGraphicObjectInstance
bool LessRenderOrder(CEffectInstance* pkEftInst); bool LessRenderOrder(CEffectInstance* pkEftInst);
void SetEffectDataPointer(CEffectData * pEffectData); void SetEffectDataPointer(CEffectData * pEffectData);
// Returns the pointer to the effect data associated with this instance.
CEffectData* GetEffectDataPointer() const
{
return m_pkEftData;
}
void Clear(); void Clear();
BOOL isAlive(); BOOL isAlive();
@@ -62,6 +55,9 @@ class CEffectInstance : public CGraphicObjectInstance
void OnRenderShadow() {} // Not used void OnRenderShadow() {} // Not used
void OnRenderPCBlocker() {} // Not used void OnRenderPCBlocker() {} // Not used
void BatchParticles();
void RenderMeshes();
protected: protected:
void __Initialize(); void __Initialize();
@@ -84,7 +80,7 @@ class CEffectInstance : public CGraphicObjectInstance
std::vector<CEffectMeshInstance*> m_MeshInstanceVector; std::vector<CEffectMeshInstance*> m_MeshInstanceVector;
std::vector<CLightInstance*> m_LightInstanceVector; std::vector<CLightInstance*> m_LightInstanceVector;
NSound::TSoundInstanceVector * m_pSoundInstanceVector; TSoundInstanceVector * m_pSoundInstanceVector;
float m_fBoundingSphereRadius; float m_fBoundingSphereRadius;
D3DXVECTOR3 m_v3BoundingSpherePosition; D3DXVECTOR3 m_v3BoundingSpherePosition;
@@ -92,7 +88,6 @@ class CEffectInstance : public CGraphicObjectInstance
float m_fLastTime; float m_fLastTime;
public: public:
static CDynamicPool<CEffectInstance> ms_kPool; static CDynamicPool<CEffectInstance> ms_kPool;
static int ms_iRenderingEffectCount; static int ms_iRenderingEffectCount;
}; };

View File

@@ -1,13 +1,15 @@
#include "StdAfx.h" #include "StdAfx.h"
#include "EterBase/Random.h" #include "../eterBase/Random.h"
#include "Eterlib/StateManager.h" #include "../eterlib/StateManager.h"
#include "EffectManager.h" #include "EffectManager.h"
extern std::unordered_map<LPDIRECT3DTEXTURE9, std::unordered_map<uint32_t, std::vector<TPDTVertex>>> g_particleVertexBatch;
void CEffectManager::GetInfo(std::string* pstInfo) void CEffectManager::GetInfo(std::string* pstInfo)
{ {
char szInfo[256]; char szInfo[256];
sprintf(szInfo, "Effect: Inst - ED %zd, EI %zd Pool - PSI %zd, MI %zd, LI %zd, PI %zd, EI %zd, ED %zd, PSD %zd, EM %zd, LD %zd", sprintf(szInfo, "Effect: Inst - ED %d, EI %d Pool - PSI %d, MI %d, LI %d, PI %d, EI %d, ED %d, PSD %d, EM %d, LD %d",
m_kEftDataMap.size(), m_kEftDataMap.size(),
m_kEftInstMap.size(), m_kEftInstMap.size(),
CParticleSystemInstance::ms_kPool.GetCapacity(), CParticleSystemInstance::ms_kPool.GetCapacity(),
@@ -80,50 +82,15 @@ void CEffectManager::Update()
} }
} }
struct CEffectManager_LessEffectInstancePtrRenderOrder
{
bool operator() (CEffectInstance* pkLeft, CEffectInstance* pkRight)
{
return pkLeft->LessRenderOrder(pkRight);
}
};
struct CEffectManager_FEffectInstanceRender
{
inline void operator () (CEffectInstance * pkEftInst)
{
pkEftInst->Render();
}
};
void CEffectManager::Render() void CEffectManager::Render()
{ {
STATEMANAGER.SetTexture(0, NULL); STATEMANAGER.SetTexture(0, NULL);
STATEMANAGER.SetTexture(1, NULL); STATEMANAGER.SetTexture(1, NULL);
if (m_isDisableSortRendering)
{
for (TEffectInstanceMap::iterator itor = m_kEftInstMap.begin(); itor != m_kEftInstMap.end();)
{
CEffectInstance * pEffectInstance = itor->second;
pEffectInstance->Render();
++itor;
}
}
else
{
static std::vector<CEffectInstance*> s_kVct_pkEftInstSort;
s_kVct_pkEftInstSort.clear();
TEffectInstanceMap& rkMap_pkEftInstSrc=m_kEftInstMap; g_particleVertexBatch.clear();
TEffectInstanceMap::iterator i;
for (i=rkMap_pkEftInstSrc.begin(); i!=rkMap_pkEftInstSrc.end(); ++i)
s_kVct_pkEftInstSort.push_back(i->second);
std::sort(s_kVct_pkEftInstSort.begin(), s_kVct_pkEftInstSort.end(), CEffectManager_LessEffectInstancePtrRenderOrder()); __RenderParticles();
std::for_each(s_kVct_pkEftInstSort.begin(), s_kVct_pkEftInstSort.end(), CEffectManager_FEffectInstanceRender()); __RenderMeshes();
}
} }
BOOL CEffectManager::RegisterEffect(const char * c_szFileName,bool isExistDelete,bool isNeedCache) BOOL CEffectManager::RegisterEffect(const char * c_szFileName,bool isExistDelete,bool isNeedCache)
@@ -351,33 +318,6 @@ void CEffectManager::HideEffect()
m_pSelectedEffectInstance->Hide(); m_pSelectedEffectInstance->Hide();
} }
// MR-5: Fix effect rendering when actor is semi-transparent
// Credits to d1str4ught
void CEffectManager::RenderEffect()
{
if (!m_pSelectedEffectInstance)
return;
m_pSelectedEffectInstance->Render();
}
// MR-5: -- END OF -- Fix effect rendering when actor is semi-transparent
void CEffectManager::ApplyAlwaysHidden()
{
if (!m_pSelectedEffectInstance)
return;
m_pSelectedEffectInstance->ApplyAlwaysHidden();
}
void CEffectManager::ReleaseAlwaysHidden()
{
if (!m_pSelectedEffectInstance)
return;
m_pSelectedEffectInstance->ReleaseAlwaysHidden();
}
bool CEffectManager::GetEffectData(DWORD dwID, CEffectData ** ppEffect) bool CEffectManager::GetEffectData(DWORD dwID, CEffectData ** ppEffect)
{ {
TEffectDataMap::iterator itor = m_kEftDataMap.find(dwID); TEffectDataMap::iterator itor = m_kEftDataMap.find(dwID);
@@ -464,6 +404,122 @@ void CEffectManager::__DestroyEffectDataMap()
m_kEftDataMap.clear(); m_kEftDataMap.clear();
} }
void CEffectManager::__RenderParticles()
{
STATEMANAGER.SetFVF(D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1);
STATEMANAGER.SaveSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_NONE);
STATEMANAGER.SaveSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_NONE);
STATEMANAGER.SaveRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
STATEMANAGER.SaveRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
STATEMANAGER.SaveRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
STATEMANAGER.SaveRenderState(D3DRS_ALPHATESTENABLE, FALSE);
STATEMANAGER.SaveRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
STATEMANAGER.SaveRenderState(D3DRS_ZWRITEENABLE, FALSE);
STATEMANAGER.SaveRenderState(D3DRS_LIGHTING, FALSE);
STATEMANAGER.SaveTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
STATEMANAGER.SaveTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
STATEMANAGER.SaveTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
STATEMANAGER.SaveTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
STATEMANAGER.SaveTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
STATEMANAGER.SaveTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
for (auto itor = m_kEftInstMap.begin(); itor != m_kEftInstMap.end(); ++itor) {
itor->second->BatchParticles();
}
for (auto& [pTexture, keyMap] : g_particleVertexBatch) {
if (keyMap.empty())
continue;
STATEMANAGER.SetTexture(0, pTexture);
for (auto& [opKey, vtxBatch] : keyMap) {
if (vtxBatch.empty())
continue;
uint8_t* pKeyPart = (uint8_t*)&opKey;
STATEMANAGER.SetRenderState(D3DRS_SRCBLEND, pKeyPart[0]);
STATEMANAGER.SetRenderState(D3DRS_DESTBLEND, pKeyPart[1]);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, pKeyPart[2]);
STATEMANAGER.DrawPrimitiveUP(
D3DPT_TRIANGLELIST,
vtxBatch.size() / 3,
vtxBatch.data(),
sizeof(TPDTVertex));
}
}
STATEMANAGER.RestoreTextureStageState(0, D3DTSS_COLORARG1);
STATEMANAGER.RestoreTextureStageState(0, D3DTSS_COLORARG2);
STATEMANAGER.RestoreTextureStageState(0, D3DTSS_COLOROP);
STATEMANAGER.RestoreTextureStageState(0, D3DTSS_ALPHAARG1);
STATEMANAGER.RestoreTextureStageState(0, D3DTSS_ALPHAARG2);
STATEMANAGER.RestoreTextureStageState(0, D3DTSS_ALPHAOP);
STATEMANAGER.RestoreSamplerState(0, D3DSAMP_MINFILTER);
STATEMANAGER.RestoreSamplerState(0, D3DSAMP_MAGFILTER);
STATEMANAGER.RestoreRenderState(D3DRS_ALPHABLENDENABLE);
STATEMANAGER.RestoreRenderState(D3DRS_SRCBLEND);
STATEMANAGER.RestoreRenderState(D3DRS_DESTBLEND);
STATEMANAGER.RestoreRenderState(D3DRS_ALPHATESTENABLE);
STATEMANAGER.RestoreRenderState(D3DRS_CULLMODE);
STATEMANAGER.RestoreRenderState(D3DRS_ZWRITEENABLE);
STATEMANAGER.RestoreRenderState(D3DRS_LIGHTING);
}
void CEffectManager::__RenderMeshes()
{
STATEMANAGER.SetFVF(D3DFVF_XYZ | D3DFVF_TEX1);
STATEMANAGER.SaveSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_NONE);
STATEMANAGER.SaveSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_NONE);
STATEMANAGER.SaveRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
STATEMANAGER.SaveRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
STATEMANAGER.SaveRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
STATEMANAGER.SaveRenderState(D3DRS_ALPHATESTENABLE, FALSE);
STATEMANAGER.SaveRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
STATEMANAGER.SaveRenderState(D3DRS_ZWRITEENABLE, FALSE);
STATEMANAGER.SaveRenderState(D3DRS_LIGHTING, FALSE);
STATEMANAGER.SaveTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
STATEMANAGER.SaveTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TEXTURE);
STATEMANAGER.SaveTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
STATEMANAGER.SaveTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR);
STATEMANAGER.SaveTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_TEXTURE);
STATEMANAGER.SaveTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
for (auto itor = m_kEftInstMap.begin(); itor != m_kEftInstMap.end(); ++itor) {
itor->second->RenderMeshes();
}
STATEMANAGER.RestoreTextureStageState(0, D3DTSS_COLORARG1);
STATEMANAGER.RestoreTextureStageState(0, D3DTSS_COLORARG2);
STATEMANAGER.RestoreTextureStageState(0, D3DTSS_COLOROP);
STATEMANAGER.RestoreTextureStageState(0, D3DTSS_ALPHAARG1);
STATEMANAGER.RestoreTextureStageState(0, D3DTSS_ALPHAARG2);
STATEMANAGER.RestoreTextureStageState(0, D3DTSS_ALPHAOP);
STATEMANAGER.RestoreSamplerState(0, D3DSAMP_MINFILTER);
STATEMANAGER.RestoreSamplerState(0, D3DSAMP_MAGFILTER);
STATEMANAGER.RestoreRenderState(D3DRS_ALPHABLENDENABLE);
STATEMANAGER.RestoreRenderState(D3DRS_SRCBLEND);
STATEMANAGER.RestoreRenderState(D3DRS_DESTBLEND);
STATEMANAGER.RestoreRenderState(D3DRS_ALPHATESTENABLE);
STATEMANAGER.RestoreRenderState(D3DRS_CULLMODE);
STATEMANAGER.RestoreRenderState(D3DRS_ZWRITEENABLE);
STATEMANAGER.RestoreRenderState(D3DRS_LIGHTING);
}
void CEffectManager::Destroy() void CEffectManager::Destroy()
{ {
__DestroyEffectInstanceMap(); __DestroyEffectInstanceMap();
@@ -489,26 +545,5 @@ CEffectManager::~CEffectManager()
Destroy(); Destroy();
} }
DWORD CEffectManager::GetSelectedEffectDataCRC() const
{
if (!m_pSelectedEffectInstance)
return 0;
CEffectData* pData = m_pSelectedEffectInstance->GetEffectDataPointer();
if (!pData)
return 0;
const char* cszFile = pData->GetFileName();
if (!cszFile || !cszFile[0])
return 0;
std::string str;
StringPath(cszFile, str);
return GetCaseCRC32(str.c_str(), (int)str.length());
}
// just for map effect // just for map effect

View File

@@ -1,6 +1,5 @@
#pragma once #pragma once
#include "StdAfx.h"
#include "EffectInstance.h" #include "EffectInstance.h"
class CEffectManager : public CScreen, public CSingleton<CEffectManager> class CEffectManager : public CScreen, public CSingleton<CEffectManager>
@@ -56,13 +55,6 @@ class CEffectManager : public CScreen, public CSingleton<CEffectManager>
void ShowEffect(); void ShowEffect();
void HideEffect(); void HideEffect();
// MR-5: Fix effect rendering when actor is semi-transparent
// Credits to d1str4ught
void RenderEffect();
// MR-5: -- END OF -- Fix effect rendering when actor is semi-transparent
void ApplyAlwaysHidden();
void ReleaseAlwaysHidden();
// Temporary function // Temporary function
DWORD GetRandomEffect(); DWORD GetRandomEffect();
@@ -77,9 +69,6 @@ class CEffectManager : public CScreen, public CSingleton<CEffectManager>
int GetRenderingEffectCount(); int GetRenderingEffectCount();
// Return the CRC of the effect-data for the selected effect instance.
DWORD GetSelectedEffectDataCRC() const;
protected: protected:
void __Initialize(); void __Initialize();
@@ -87,6 +76,9 @@ class CEffectManager : public CScreen, public CSingleton<CEffectManager>
void __DestroyEffectCacheMap(); void __DestroyEffectCacheMap();
void __DestroyEffectDataMap(); void __DestroyEffectDataMap();
void __RenderParticles();
void __RenderMeshes();
protected: protected:
bool m_isDisableSortRendering; bool m_isDisableSortRendering;
TEffectDataMap m_kEftDataMap; TEffectDataMap m_kEftDataMap;

View File

@@ -1,7 +1,7 @@
#include "StdAfx.h" #include "StdAfx.h"
#include "Eterlib/StateManager.h" #include "../eterlib/StateManager.h"
#include "Eterlib/ResourceManager.h" #include "../eterlib/ResourceManager.h"
#include "PackLib/PackManager.h" #include "../eterpack/EterPackManager.h"
#include "EffectMesh.h" #include "EffectMesh.h"
CDynamicPool<CEffectMesh::SEffectMeshData> CEffectMesh::SEffectMeshData::ms_kPool; CDynamicPool<CEffectMesh::SEffectMeshData> CEffectMesh::SEffectMeshData::ms_kPool;
@@ -192,14 +192,15 @@ BOOL CEffectMesh::__LoadData_Ver002(int iSize, const BYTE * c_pbBuf)
if (0 == strExtension.compare("ifl")) if (0 == strExtension.compare("ifl"))
{ {
TPackFile File; LPCVOID pMotionData;
CMappedFile File;
if (CPackManager::Instance().GetFile(pMeshData->szDiffuseMapFileName, File)) if (CEterPackManager::Instance().Get(File, pMeshData->szDiffuseMapFileName, &pMotionData))
{ {
CMemoryTextFileLoader textFileLoader; CMemoryTextFileLoader textFileLoader;
std::vector<std::string> stTokenVector; std::vector<std::string> stTokenVector;
textFileLoader.Bind(File.size(), File.data()); textFileLoader.Bind(File.Size(), pMotionData);
std::string strPathName; std::string strPathName;
GetOnlyPathName(pMeshData->szDiffuseMapFileName, strPathName); GetOnlyPathName(pMeshData->szDiffuseMapFileName, strPathName);
@@ -336,14 +337,15 @@ BOOL CEffectMesh::__LoadData_Ver001(int iSize, const BYTE * c_pbBuf)
if (0 == strExtension.compare("ifl")) if (0 == strExtension.compare("ifl"))
{ {
TPackFile File; LPCVOID pMotionData;
CMappedFile File;
if (CPackManager::Instance().GetFile(pMeshData->szDiffuseMapFileName, File)) if (CEterPackManager::Instance().Get(File, pMeshData->szDiffuseMapFileName, &pMotionData))
{ {
CMemoryTextFileLoader textFileLoader; CMemoryTextFileLoader textFileLoader;
std::vector<std::string> stTokenVector; std::vector<std::string> stTokenVector;
textFileLoader.Bind(File.size(), File.data()); textFileLoader.Bind(File.Size(), pMotionData);
std::string strPathName; std::string strPathName;
GetOnlyPathName(pMeshData->szDiffuseMapFileName, strPathName); GetOnlyPathName(pMeshData->szDiffuseMapFileName, strPathName);

View File

@@ -2,10 +2,10 @@
#include <d3dx9.h> #include <d3dx9.h>
#include "Eterlib/GrpScreen.h" #include "../eterlib/GrpScreen.h"
#include "Eterlib/Resource.h" #include "../eterlib/Resource.h"
#include "Eterlib/GrpImageInstance.h" #include "../eterlib/GrpImageInstance.h"
#include "EterLib/TextFileLoader.h" #include "../eterLib/TextFileLoader.h"
#include "Type.h" #include "Type.h"
#include "EffectElementBase.h" #include "EffectElementBase.h"

View File

@@ -1,8 +1,8 @@
#include "StdAfx.h" #include "StdAfx.h"
#include "EterLib/StateManager.h" #include "../eterLib/StateManager.h"
#include "EterLib/ResourceManager.h" #include "../eterLib/ResourceManager.h"
#include "EffectMeshInstance.h" #include "EffectMeshInstance.h"
#include "Eterlib/GrpMath.h" #include "../eterlib/GrpMath.h"
CDynamicPool<CEffectMeshInstance> CEffectMeshInstance::ms_kPool; CDynamicPool<CEffectMeshInstance> CEffectMeshInstance::ms_kPool;
@@ -167,8 +167,7 @@ void CEffectMeshInstance::OnRender()
} }
Color.a = fAlpha * rFrameData.fVisibility; Color.a = fAlpha * rFrameData.fVisibility;
STATEMANAGER.SetRenderState(D3DRS_TEXTUREFACTOR, DWORD(Color)); STATEMANAGER.SetRenderState(D3DRS_TEXTUREFACTOR, Color);
STATEMANAGER.SetFVF(D3DFVF_XYZ | D3DFVF_TEX1);
STATEMANAGER.DrawPrimitiveUP(D3DPT_TRIANGLELIST, STATEMANAGER.DrawPrimitiveUP(D3DPT_TRIANGLELIST,
rFrameData.dwIndexCount/3, rFrameData.dwIndexCount/3,
&rFrameData.PDTVertexVector[0], &rFrameData.PDTVertexVector[0],

View File

@@ -1,7 +1,7 @@
#pragma once #pragma once
#include "Eterlib/GrpScreen.h" #include "../eterlib/GrpScreen.h"
#include "Eterlib/GrpImageInstance.h" #include "../eterlib/GrpImageInstance.h"
#include "EffectElementBaseInstance.h" #include "EffectElementBaseInstance.h"
#include "FrameController.h" #include "FrameController.h"
#include "EffectMesh.h" #include "EffectMesh.h"

View File

@@ -156,6 +156,12 @@ void CParticleInstance::UpdateColor(float time, float elapsedTime)
return; return;
m_Color = GetTimeEventBlendValue(time, m_pParticleProperty->m_TimeEventColor); m_Color = GetTimeEventBlendValue(time, m_pParticleProperty->m_TimeEventColor);
#ifdef ENABLE_BATCHED_PARTICLE_RENDERING
for (auto& vtx : m_ParticleMesh) {
vtx.diffuse = m_Color;
}
#endif
} }
void CParticleInstance::UpdateGravity(float time, float elapsedTime) void CParticleInstance::UpdateGravity(float time, float elapsedTime)
@@ -179,7 +185,10 @@ void CParticleInstance::UpdateAirResistance(float time, float elapsedTime)
void CParticleInstance::Transform(const D3DXMATRIX * c_matLocal) void CParticleInstance::Transform(const D3DXMATRIX * c_matLocal)
{ {
#ifndef ENABLE_BATCHED_PARTICLE_RENDERING
STATEMANAGER.SetRenderState(D3DRS_TEXTUREFACTOR, m_Color); STATEMANAGER.SetRenderState(D3DRS_TEXTUREFACTOR, m_Color);
#endif
/////
D3DXVECTOR3 v3Up; D3DXVECTOR3 v3Up;
D3DXVECTOR3 v3Cross; D3DXVECTOR3 v3Cross;
@@ -313,24 +322,63 @@ void CParticleInstance::Transform(const D3DXMATRIX * c_matLocal)
{ {
D3DXVECTOR3 v3Position; D3DXVECTOR3 v3Position;
D3DXVec3TransformCoord(&v3Position, &m_v3Position, c_matLocal); D3DXVec3TransformCoord(&v3Position, &m_v3Position, c_matLocal);
m_ParticleMesh[0].position = v3Position - v3Up + v3Cross;
m_ParticleMesh[1].position = v3Position - v3Up - v3Cross; D3DXVECTOR3 p0 = v3Position - v3Up + v3Cross; // bottom-left
m_ParticleMesh[2].position = v3Position + v3Up + v3Cross; D3DXVECTOR3 p1 = v3Position - v3Up - v3Cross; // bottom-right
m_ParticleMesh[3].position = v3Position + v3Up - v3Cross; D3DXVECTOR3 p2 = v3Position + v3Up + v3Cross; // top-left
D3DXVECTOR3 p3 = v3Position + v3Up - v3Cross; // top-right
#ifdef ENABLE_BATCHED_PARTICLE_RENDERING
// triangle 1: p0, p1, p2
m_ParticleMesh[0].position = p0;
m_ParticleMesh[1].position = p1;
m_ParticleMesh[2].position = p2;
// triangle 2: p2, p1, p3
m_ParticleMesh[3].position = p2;
m_ParticleMesh[4].position = p1;
m_ParticleMesh[5].position = p3;
#else
m_ParticleMesh[0].position = p0;
m_ParticleMesh[1].position = p1;
m_ParticleMesh[2].position = p2;
m_ParticleMesh[3].position = p3;
#endif
} }
else else
{ {
m_ParticleMesh[0].position = m_v3Position - v3Up + v3Cross; D3DXVECTOR3 p0 = m_v3Position - v3Up + v3Cross; // bottom-left
m_ParticleMesh[1].position = m_v3Position - v3Up - v3Cross; D3DXVECTOR3 p1 = m_v3Position - v3Up - v3Cross; // bottom-right
m_ParticleMesh[2].position = m_v3Position + v3Up + v3Cross; D3DXVECTOR3 p2 = m_v3Position + v3Up + v3Cross; // top-left
m_ParticleMesh[3].position = m_v3Position + v3Up - v3Cross; D3DXVECTOR3 p3 = m_v3Position + v3Up - v3Cross; // top-right
#ifdef ENABLE_BATCHED_PARTICLE_RENDERING
// triangle 1: p0, p1, p2
m_ParticleMesh[0].position = p0;
m_ParticleMesh[1].position = p1;
m_ParticleMesh[2].position = p2;
// triangle 2: p2, p1, p3
m_ParticleMesh[3].position = p2;
m_ParticleMesh[4].position = p1;
m_ParticleMesh[5].position = p3;
#else
m_ParticleMesh[0].position = p0;
m_ParticleMesh[1].position = p1;
m_ParticleMesh[2].position = p2;
m_ParticleMesh[3].position = p3;
#endif
} }
} }
void CParticleInstance::Transform(const D3DXMATRIX * c_matLocal, const float c_fZRotation) void CParticleInstance::Transform(const D3DXMATRIX * c_matLocal, const float c_fZRotation)
{ {
#ifndef ENABLE_BATCHED_PARTICLE_RENDERING
STATEMANAGER.SetRenderState(D3DRS_TEXTUREFACTOR, m_Color); STATEMANAGER.SetRenderState(D3DRS_TEXTUREFACTOR, m_Color);
#endif
/////
D3DXVECTOR3 v3Up; D3DXVECTOR3 v3Up;
D3DXVECTOR3 v3Cross; D3DXVECTOR3 v3Cross;
@@ -462,17 +510,52 @@ void CParticleInstance::Transform(const D3DXMATRIX * c_matLocal, const float c_f
{ {
D3DXVECTOR3 v3Position; D3DXVECTOR3 v3Position;
D3DXVec3TransformCoord(&v3Position, &m_v3Position, c_matLocal); D3DXVec3TransformCoord(&v3Position, &m_v3Position, c_matLocal);
m_ParticleMesh[0].position = v3Position - v3Up + v3Cross;
m_ParticleMesh[1].position = v3Position - v3Up - v3Cross; D3DXVECTOR3 p0 = v3Position - v3Up + v3Cross; // bottom-left
m_ParticleMesh[2].position = v3Position + v3Up + v3Cross; D3DXVECTOR3 p1 = v3Position - v3Up - v3Cross; // bottom-right
m_ParticleMesh[3].position = v3Position + v3Up - v3Cross; D3DXVECTOR3 p2 = v3Position + v3Up + v3Cross; // top-left
D3DXVECTOR3 p3 = v3Position + v3Up - v3Cross; // top-right
#ifdef ENABLE_BATCHED_PARTICLE_RENDERING
// triangle 1: p0, p1, p2
m_ParticleMesh[0].position = p0;
m_ParticleMesh[1].position = p1;
m_ParticleMesh[2].position = p2;
// triangle 2: p2, p1, p3
m_ParticleMesh[3].position = p2;
m_ParticleMesh[4].position = p1;
m_ParticleMesh[5].position = p3;
#else
m_ParticleMesh[0].position = p0;
m_ParticleMesh[1].position = p1;
m_ParticleMesh[2].position = p2;
m_ParticleMesh[3].position = p3;
#endif
} }
else else
{ {
m_ParticleMesh[0].position = m_v3Position - v3Up + v3Cross; D3DXVECTOR3 p0 = m_v3Position - v3Up + v3Cross; // bottom-left
m_ParticleMesh[1].position = m_v3Position - v3Up - v3Cross; D3DXVECTOR3 p1 = m_v3Position - v3Up - v3Cross; // bottom-right
m_ParticleMesh[2].position = m_v3Position + v3Up + v3Cross; D3DXVECTOR3 p2 = m_v3Position + v3Up + v3Cross; // top-left
m_ParticleMesh[3].position = m_v3Position + v3Up - v3Cross; D3DXVECTOR3 p3 = m_v3Position + v3Up - v3Cross; // top-right
#ifdef ENABLE_BATCHED_PARTICLE_RENDERING
// triangle 1: p0, p1, p2
m_ParticleMesh[0].position = p0;
m_ParticleMesh[1].position = p1;
m_ParticleMesh[2].position = p2;
// triangle 2: p2, p1, p3
m_ParticleMesh[3].position = p2;
m_ParticleMesh[4].position = p1;
m_ParticleMesh[5].position = p3;
#else
m_ParticleMesh[0].position = p0;
m_ParticleMesh[1].position = p1;
m_ParticleMesh[2].position = p2;
m_ParticleMesh[3].position = p3;
#endif
} }
} }
@@ -490,14 +573,29 @@ void CParticleInstance::__Initialize()
m_v2Scale = D3DXVECTOR2(1.0f, 1.0f); m_v2Scale = D3DXVECTOR2(1.0f, 1.0f);
m_Color = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f); m_Color = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
#ifdef ENABLE_BATCHED_PARTICLE_RENDERING
for (auto& vtx : m_ParticleMesh) {
vtx.diffuse = m_Color;
}
#endif
m_byFrameIndex = 0; m_byFrameIndex = 0;
m_rotationType = CParticleProperty::ROTATION_TYPE_NONE; m_rotationType = CParticleProperty::ROTATION_TYPE_NONE;
m_fFrameTime = 0; m_fFrameTime = 0;
#ifdef ENABLE_BATCHED_PARTICLE_RENDERING
m_ParticleMesh[0].texCoord = D3DXVECTOR2(0.0f, 1.0f);
m_ParticleMesh[1].texCoord = D3DXVECTOR2(0.0f, 0.0f);
m_ParticleMesh[2].texCoord = D3DXVECTOR2(1.0f, 1.0f);
m_ParticleMesh[3].texCoord = D3DXVECTOR2(1.0f, 1.0f);
m_ParticleMesh[4].texCoord = D3DXVECTOR2(0.0f, 0.0f);
m_ParticleMesh[5].texCoord = D3DXVECTOR2(1.0f, 0.0f);
#else
m_ParticleMesh[0].texCoord = D3DXVECTOR2(0.0f, 1.0f); m_ParticleMesh[0].texCoord = D3DXVECTOR2(0.0f, 1.0f);
m_ParticleMesh[1].texCoord = D3DXVECTOR2(0.0f, 0.0f); m_ParticleMesh[1].texCoord = D3DXVECTOR2(0.0f, 0.0f);
m_ParticleMesh[2].texCoord = D3DXVECTOR2(1.0f, 1.0f); m_ParticleMesh[2].texCoord = D3DXVECTOR2(1.0f, 1.0f);
m_ParticleMesh[3].texCoord = D3DXVECTOR2(1.0f, 0.0f); m_ParticleMesh[3].texCoord = D3DXVECTOR2(1.0f, 0.0f);
#endif
} }
CParticleInstance::CParticleInstance() CParticleInstance::CParticleInstance()
@@ -510,7 +608,11 @@ CParticleInstance::~CParticleInstance()
Destroy(); Destroy();
} }
TPTVertex * CParticleInstance::GetParticleMeshPointer() #ifdef ENABLE_BATCHED_PARTICLE_RENDERING
const std::array<TPDTVertex, 6>& CParticleInstance::GetParticleMeshPointer()
#else
const std::array<TPTVertex, 4>& CParticleInstance::GetParticleMeshPointer()
#endif
{ {
return m_ParticleMesh; return m_ParticleMesh;
} }

View File

@@ -1,8 +1,11 @@
#pragma once #pragma once
#include "UserInterface/Locale_inc.h"
#include "Type.h" #include "Type.h"
#include "Eterlib/GrpBase.h" #include "Eterlib/GrpBase.h"
#include "EterLib/Pool.h" #include "EterLib/Pool.h"
#include <array>
class CParticleProperty; class CParticleProperty;
class CEmitterProperty; class CEmitterProperty;
@@ -38,6 +41,7 @@ class CParticleInstance
D3DXVECTOR2 m_v2Scale; D3DXVECTOR2 m_v2Scale;
float m_fRotation; float m_fRotation;
D3DXCOLOR m_Color; D3DXCOLOR m_Color;
BYTE m_byTextureAnimationType; BYTE m_byTextureAnimationType;
@@ -64,7 +68,11 @@ class CParticleInstance
void Transform(const D3DXMATRIX * c_matLocal=NULL); void Transform(const D3DXMATRIX * c_matLocal=NULL);
void Transform(const D3DXMATRIX * c_matLocal, const float c_fZRotation); void Transform(const D3DXMATRIX * c_matLocal, const float c_fZRotation);
TPTVertex * GetParticleMeshPointer(); #ifdef ENABLE_BATCHED_PARTICLE_RENDERING
const std::array<TPDTVertex, 6>& GetParticleMeshPointer();
#else
const std::array<TPTVertex, 4>& GetParticleMeshPointer();
#endif
void DeleteThis(); void DeleteThis();
@@ -72,7 +80,12 @@ class CParticleInstance
protected: protected:
void __Initialize(); void __Initialize();
TPTVertex m_ParticleMesh[4];
#ifdef ENABLE_BATCHED_PARTICLE_RENDERING
std::array<TPDTVertex, 6> m_ParticleMesh;
#else
std::array<TPTVertex, 4> m_ParticleMesh;
#endif
public: public:
static CDynamicPool<CParticleInstance> ms_kPool; static CDynamicPool<CParticleInstance> ms_kPool;

View File

@@ -1,11 +1,15 @@
#include "StdAfx.h" #include "StdAfx.h"
#include "ParticleProperty.h" #include "ParticleProperty.h"
#include "Eterlib/ResourceManager.h" #include "../eterlib/ResourceManager.h"
void CParticleProperty::InsertTexture(const char * c_szFileName) void CParticleProperty::InsertTexture(const char * c_szFileName)
{ {
CGraphicImage * pImage = (CGraphicImage *)CResourceManager::Instance().GetResourcePointer(c_szFileName); CGraphicImage * pImage = (CGraphicImage *)CResourceManager::Instance().GetResourcePointer(c_szFileName);
m_ImageVector.push_back(pImage); m_ImageVector.push_back(pImage);
#ifdef WORLD_EDITOR
m_TextureNameVector.push_back(c_szFileName);
#endif
} }
bool CParticleProperty::SetTexture(const char * c_szFileName) bool CParticleProperty::SetTexture(const char * c_szFileName)
@@ -16,6 +20,9 @@ bool CParticleProperty::SetTexture(const char * c_szFileName)
return false; return false;
} }
m_ImageVector.clear(); m_ImageVector.clear();
#ifdef WORLD_EDITOR
m_TextureNameVector.clear();
#endif
InsertTexture(c_szFileName); InsertTexture(c_szFileName);
return true; return true;
} }
@@ -49,7 +56,15 @@ void CParticleProperty::Clear()
m_TimeEventScaleX.clear(); m_TimeEventScaleX.clear();
m_TimeEventScaleY.clear(); m_TimeEventScaleY.clear();
//m_TimeEventScaleXY.clear(); //m_TimeEventScaleXY.clear();
#ifdef WORLD_EDITOR
m_TimeEventColorRed.clear();
m_TimeEventColorGreen.clear();
m_TimeEventColorBlue.clear();
m_TimeEventAlpha.clear();
m_TextureNameVector.clear();
#else
m_TimeEventColor.clear(); m_TimeEventColor.clear();
#endif
m_TimeEventRotation.clear(); m_TimeEventRotation.clear();
m_ImageVector.clear(); m_ImageVector.clear();
@@ -88,7 +103,16 @@ CParticleProperty & CParticleProperty::operator = ( const CParticleProperty& c_P
m_TimeEventScaleX = c_ParticleProperty.m_TimeEventScaleX; m_TimeEventScaleX = c_ParticleProperty.m_TimeEventScaleX;
m_TimeEventScaleY = c_ParticleProperty.m_TimeEventScaleY; m_TimeEventScaleY = c_ParticleProperty.m_TimeEventScaleY;
#ifdef WORLD_EDITOR
m_TimeEventColorRed = c_ParticleProperty.m_TimeEventColorRed;
m_TimeEventColorGreen = c_ParticleProperty.m_TimeEventColorGreen;
m_TimeEventColorBlue = c_ParticleProperty.m_TimeEventColorBlue;
m_TimeEventAlpha = c_ParticleProperty.m_TimeEventAlpha;
m_TextureNameVector = c_ParticleProperty.m_TextureNameVector;
#else
m_TimeEventColor = c_ParticleProperty.m_TimeEventColor; m_TimeEventColor = c_ParticleProperty.m_TimeEventColor;
#endif
m_TimeEventRotation = c_ParticleProperty.m_TimeEventRotation; m_TimeEventRotation = c_ParticleProperty.m_TimeEventRotation;
m_ImageVector = c_ParticleProperty.m_ImageVector; m_ImageVector = c_ParticleProperty.m_ImageVector;

View File

@@ -1,7 +1,7 @@
#pragma once #pragma once
#include <vector> #include <vector>
#include "Eterlib/GrpImageInstance.h" #include "../eterlib/GrpImageInstance.h"
#include "Type.h" #include "Type.h"
@@ -75,7 +75,16 @@ class CParticleProperty
TTimeEventTableFloat m_TimeEventScaleX; TTimeEventTableFloat m_TimeEventScaleX;
TTimeEventTableFloat m_TimeEventScaleY; TTimeEventTableFloat m_TimeEventScaleY;
#ifdef WORLD_EDITOR
TTimeEventTableFloat m_TimeEventColorRed;
TTimeEventTableFloat m_TimeEventColorGreen;
TTimeEventTableFloat m_TimeEventColorBlue;
TTimeEventTableFloat m_TimeEventAlpha;
std::vector<std::string> m_TextureNameVector;
#else
TTimeEventTableColor m_TimeEventColor; TTimeEventTableColor m_TimeEventColor;
#endif
TTimeEventTableFloat m_TimeEventRotation; TTimeEventTableFloat m_TimeEventRotation;
std::vector<CGraphicImage*> m_ImageVector; std::vector<CGraphicImage*> m_ImageVector;

View File

@@ -210,6 +210,17 @@ BOOL CParticleSystemData::OnLoadScript(CTextFileLoader & rTextFileLoader)
if (!GetTokenTimeEventFloat(rTextFileLoader, "timeeventscaley", &m_ParticleProperty.m_TimeEventScaleY)) if (!GetTokenTimeEventFloat(rTextFileLoader, "timeeventscaley", &m_ParticleProperty.m_TimeEventScaleY))
return FALSE; return FALSE;
#ifdef WORLD_EDITOR
if (!GetTokenTimeEventFloat(rTextFileLoader, "timeeventcolorred", &m_ParticleProperty.m_TimeEventColorRed))
return FALSE;
if (!GetTokenTimeEventFloat(rTextFileLoader, "timeeventcolorgreen", &m_ParticleProperty.m_TimeEventColorGreen))
return FALSE;
if (!GetTokenTimeEventFloat(rTextFileLoader, "timeeventcolorblue", &m_ParticleProperty.m_TimeEventColorBlue))
return FALSE;
if (!GetTokenTimeEventFloat(rTextFileLoader, "timeeventalpha", &m_ParticleProperty.m_TimeEventAlpha))
return FALSE;
#else
TTimeEventTableFloat TimeEventR; TTimeEventTableFloat TimeEventR;
TTimeEventTableFloat TimeEventB; TTimeEventTableFloat TimeEventB;
TTimeEventTableFloat TimeEventG; TTimeEventTableFloat TimeEventG;
@@ -246,13 +257,16 @@ BOOL CParticleSystemData::OnLoadScript(CTextFileLoader & rTextFileLoader)
fA = GetTimeEventBlendValue(fTime, TimeEventA); fA = GetTimeEventBlendValue(fTime, TimeEventA);
TTimeEventTypeColor t; TTimeEventTypeColor t;
t.m_fTime = fTime; t.m_fTime = fTime;
t.m_Value.r = fR; D3DXCOLOR c;
t.m_Value.g = fG; c.r = fR;
t.m_Value.b = fB; c.g = fG;
t.m_Value.a = fA; c.b = fB;
c.a = fA;
t.m_Value = c;
m_ParticleProperty.m_TimeEventColor.push_back(t); m_ParticleProperty.m_TimeEventColor.push_back(t);
} }
} }
#endif
if (!GetTokenTimeEventFloat(rTextFileLoader, "timeeventrotation", &m_ParticleProperty.m_TimeEventRotation)) if (!GetTokenTimeEventFloat(rTextFileLoader, "timeeventrotation", &m_ParticleProperty.m_TimeEventRotation))
return FALSE; return FALSE;

View File

@@ -1,6 +1,6 @@
#pragma once #pragma once
#include "EterLib/TextFileLoader.h" #include "../eterLib/TextFileLoader.h"
#include "EffectElementBase.h" #include "EffectElementBase.h"
#include "EmitterProperty.h" #include "EmitterProperty.h"

View File

@@ -1,10 +1,12 @@
#include "StdAfx.h" #include "StdAfx.h"
#include "EterBase/Random.h" #include "../eterBase/Random.h"
#include "EterLib/StateManager.h" #include "../eterLib/StateManager.h"
#include "ParticleSystemData.h" #include "ParticleSystemData.h"
#include "ParticleSystemInstance.h" #include "ParticleSystemInstance.h"
#include "ParticleInstance.h" #include "ParticleInstance.h"
std::unordered_map<LPDIRECT3DTEXTURE9, std::unordered_map<uint32_t, std::vector<TPDTVertex>>> g_particleVertexBatch;
CDynamicPool<CParticleSystemInstance> CParticleSystemInstance::ms_kPool; CDynamicPool<CParticleSystemInstance> CParticleSystemInstance::ms_kPool;
void CParticleSystemInstance::DestroySystem() void CParticleSystemInstance::DestroySystem()
@@ -248,7 +250,14 @@ void CParticleSystemInstance::CreateParticles(float fElapsedTime)
pInstance->m_v2Scale.x = m_pParticleProperty->m_TimeEventScaleX.front().m_Value; pInstance->m_v2Scale.x = m_pParticleProperty->m_TimeEventScaleX.front().m_Value;
pInstance->m_v2Scale.y= m_pParticleProperty->m_TimeEventScaleY.front().m_Value; pInstance->m_v2Scale.y= m_pParticleProperty->m_TimeEventScaleY.front().m_Value;
//pInstance->m_v2Scale = m_pParticleProperty->m_TimeEventScaleXY.front().m_Value; //pInstance->m_v2Scale = m_pParticleProperty->m_TimeEventScaleXY.front().m_Value;
#ifdef WORLD_EDITOR
pInstance->m_Color.r = m_pParticleProperty->m_TimeEventColorRed.front().m_Value;
pInstance->m_Color.g = m_pParticleProperty->m_TimeEventColorGreen.front().m_Value;
pInstance->m_Color.b = m_pParticleProperty->m_TimeEventColorBlue.front().m_Value;
pInstance->m_Color.a = m_pParticleProperty->m_TimeEventAlpha.front().m_Value;
#else
pInstance->m_Color = m_pParticleProperty->m_TimeEventColor.front().m_Value; pInstance->m_Color = m_pParticleProperty->m_TimeEventColor.front().m_Value;
#endif
} }
m_ParticleInstanceListVector[pInstance->m_byFrameIndex].push_back(pInstance); m_ParticleInstanceListVector[pInstance->m_byFrameIndex].push_back(pInstance);
@@ -336,80 +345,111 @@ namespace NParticleRenderer
struct TwoSideRenderer struct TwoSideRenderer
{ {
const D3DXMATRIX * pmat; const D3DXMATRIX * pmat;
TwoSideRenderer(const D3DXMATRIX * pmat=NULL) uint32_t opKey;
: pmat(pmat)
TwoSideRenderer(uint32_t key, const D3DXMATRIX * pmat=NULL)
: opKey(key), pmat(pmat)
{ {
} }
inline void operator () (CParticleInstance * pInstance) inline void operator () (CParticleInstance * pInstance, LPDIRECT3DTEXTURE9 pTexture)
{ {
auto& vtxBatch = g_particleVertexBatch[pTexture][opKey];
const auto& particleMesh = pInstance->GetParticleMeshPointer();
pInstance->Transform(pmat,D3DXToRadian(-30.0f)); pInstance->Transform(pmat,D3DXToRadian(-30.0f));
STATEMANAGER.DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, pInstance->GetParticleMeshPointer(), sizeof(TPTVertex)); vtxBatch.insert(vtxBatch.end(), particleMesh.begin(), particleMesh.end());
pInstance->Transform(pmat,D3DXToRadian(+30.0f)); pInstance->Transform(pmat,D3DXToRadian(+30.0f));
STATEMANAGER.DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, pInstance->GetParticleMeshPointer(), sizeof(TPTVertex)); vtxBatch.insert(vtxBatch.end(), particleMesh.begin(), particleMesh.end());
} }
}; };
struct ThreeSideRenderer struct ThreeSideRenderer
{ {
const D3DXMATRIX * pmat; const D3DXMATRIX * pmat;
ThreeSideRenderer(const D3DXMATRIX * pmat=NULL) uint32_t opKey;
: pmat(pmat)
ThreeSideRenderer(uint32_t key, const D3DXMATRIX * pmat=NULL)
: opKey(key), pmat(pmat)
{ {
} }
inline void operator () (CParticleInstance * pInstance) inline void operator () (CParticleInstance* pInstance, LPDIRECT3DTEXTURE9 pTexture)
{ {
auto& vtxBatch = g_particleVertexBatch[pTexture][opKey];
const auto& particleMesh = pInstance->GetParticleMeshPointer();
pInstance->Transform(pmat); pInstance->Transform(pmat);
STATEMANAGER.DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, pInstance->GetParticleMeshPointer(), sizeof(TPTVertex)); vtxBatch.insert(vtxBatch.end(), particleMesh.begin(), particleMesh.end());
pInstance->Transform(pmat,D3DXToRadian(-60.0f)); pInstance->Transform(pmat,D3DXToRadian(-60.0f));
STATEMANAGER.DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, pInstance->GetParticleMeshPointer(), sizeof(TPTVertex)); vtxBatch.insert(vtxBatch.end(), particleMesh.begin(), particleMesh.end());
pInstance->Transform(pmat,D3DXToRadian(+60.0f)); pInstance->Transform(pmat,D3DXToRadian(+60.0f));
STATEMANAGER.DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, pInstance->GetParticleMeshPointer(), sizeof(TPTVertex)); vtxBatch.insert(vtxBatch.end(), particleMesh.begin(), particleMesh.end());
} }
}; };
struct NormalRenderer struct NormalRenderer
{ {
inline void operator () (CParticleInstance * pInstance) uint32_t opKey;
NormalRenderer(uint32_t key) : opKey(key) {}
inline void operator () (CParticleInstance* pInstance, LPDIRECT3DTEXTURE9 pTexture)
{ {
auto& vtxBatch = g_particleVertexBatch[pTexture][opKey];
const auto& particleMesh = pInstance->GetParticleMeshPointer();
pInstance->Transform(); pInstance->Transform();
STATEMANAGER.DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, pInstance->GetParticleMeshPointer(), sizeof(TPTVertex)); vtxBatch.insert(vtxBatch.end(), particleMesh.begin(), particleMesh.end());
} }
}; };
struct AttachRenderer struct AttachRenderer
{ {
const D3DXMATRIX* pmat; const D3DXMATRIX* pmat;
AttachRenderer(const D3DXMATRIX * pmat) uint32_t opKey;
: pmat(pmat)
AttachRenderer(uint32_t key, const D3DXMATRIX * pmat)
: opKey(key), pmat(pmat)
{ {
} }
inline void operator () (CParticleInstance * pInstance) inline void operator () (CParticleInstance* pInstance, LPDIRECT3DTEXTURE9 pTexture)
{ {
auto& vtxBatch = g_particleVertexBatch[pTexture][opKey];
const auto& particleMesh = pInstance->GetParticleMeshPointer();
pInstance->Transform(pmat); pInstance->Transform(pmat);
STATEMANAGER.DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, pInstance->GetParticleMeshPointer(), sizeof(TPTVertex)); vtxBatch.insert(vtxBatch.end(), particleMesh.begin(), particleMesh.end());
} }
}; };
} }
void CParticleSystemInstance::OnRender() void CParticleSystemInstance::OnRender()
{ {
g_particleVertexBatch.clear();
CScreen::Identity(); CScreen::Identity();
STATEMANAGER.SetRenderState(D3DRS_SRCBLEND, m_pParticleProperty->m_bySrcBlendType);
STATEMANAGER.SetRenderState(D3DRS_DESTBLEND, m_pParticleProperty->m_byDestBlendType); uint32_t opKey;
STATEMANAGER.SetTextureStageState(0,D3DTSS_COLOROP,m_pParticleProperty->m_byColorOperationType); {
uint8_t* pKeyPart = (uint8_t*)&opKey;
pKeyPart[0] = m_pParticleProperty->m_bySrcBlendType;
pKeyPart[1] = m_pParticleProperty->m_byDestBlendType;
pKeyPart[2] = m_pParticleProperty->m_byColorOperationType;
}
if (m_pParticleProperty->m_byBillboardType < BILLBOARD_TYPE_2FACE) if (m_pParticleProperty->m_byBillboardType < BILLBOARD_TYPE_2FACE)
{ {
if (!m_pParticleProperty->m_bAttachFlag) if (!m_pParticleProperty->m_bAttachFlag)
{ {
auto obj = NParticleRenderer::NormalRenderer(); auto obj = NParticleRenderer::NormalRenderer(opKey);
ForEachParticleRendering(obj); ForEachParticleRendering(obj);
} }
else else
{ {
auto obj = NParticleRenderer::AttachRenderer(mc_pmatLocal); auto obj = NParticleRenderer::AttachRenderer(opKey, mc_pmatLocal);
ForEachParticleRendering(obj); ForEachParticleRendering(obj);
} }
} }
@@ -417,12 +457,12 @@ void CParticleSystemInstance::OnRender()
{ {
if (!m_pParticleProperty->m_bAttachFlag) if (!m_pParticleProperty->m_bAttachFlag)
{ {
auto obj = NParticleRenderer::TwoSideRenderer(); auto obj = NParticleRenderer::TwoSideRenderer(opKey);
ForEachParticleRendering(obj); ForEachParticleRendering(obj);
} }
else else
{ {
auto obj = NParticleRenderer::TwoSideRenderer(mc_pmatLocal); auto obj = NParticleRenderer::TwoSideRenderer(opKey, mc_pmatLocal);
ForEachParticleRendering(obj); ForEachParticleRendering(obj);
} }
} }
@@ -430,12 +470,90 @@ void CParticleSystemInstance::OnRender()
{ {
if (!m_pParticleProperty->m_bAttachFlag) if (!m_pParticleProperty->m_bAttachFlag)
{ {
auto obj = NParticleRenderer::ThreeSideRenderer(); auto obj = NParticleRenderer::ThreeSideRenderer(opKey);
ForEachParticleRendering(obj); ForEachParticleRendering(obj);
} }
else else
{ {
auto obj = NParticleRenderer::ThreeSideRenderer(mc_pmatLocal); auto obj = NParticleRenderer::ThreeSideRenderer(opKey, mc_pmatLocal);
ForEachParticleRendering(obj);
}
}
for (auto& [pTexture, keyMap] : g_particleVertexBatch) {
if (keyMap.empty())
continue;
STATEMANAGER.SetTexture(0, pTexture);
for (auto& [opKey, vtxBatch] : keyMap) {
if (vtxBatch.empty())
continue;
uint8_t* pKeyPart = (uint8_t*)&opKey;
STATEMANAGER.SetRenderState(D3DRS_SRCBLEND, pKeyPart[0]);
STATEMANAGER.SetRenderState(D3DRS_DESTBLEND, pKeyPart[1]);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, pKeyPart[2]);
STATEMANAGER.DrawPrimitiveUP(
D3DPT_TRIANGLELIST,
vtxBatch.size() / 3,
vtxBatch.data(),
sizeof(TPDTVertex));
}
}
}
void CParticleSystemInstance::BatchParticles()
{
CScreen::Identity();
STATEMANAGER.SetRenderState(D3DRS_SRCBLEND, m_pParticleProperty->m_bySrcBlendType);
STATEMANAGER.SetRenderState(D3DRS_DESTBLEND, m_pParticleProperty->m_byDestBlendType);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, m_pParticleProperty->m_byColorOperationType);
uint32_t opKey;
{
uint8_t* pKeyPart = (uint8_t*)&opKey;
pKeyPart[0] = m_pParticleProperty->m_bySrcBlendType;
pKeyPart[1] = m_pParticleProperty->m_byDestBlendType;
pKeyPart[2] = m_pParticleProperty->m_byColorOperationType;
}
if (m_pParticleProperty->m_byBillboardType < BILLBOARD_TYPE_2FACE)
{
if (!m_pParticleProperty->m_bAttachFlag)
{
auto obj = NParticleRenderer::NormalRenderer(opKey);
ForEachParticleRendering(obj);
}
else
{
auto obj = NParticleRenderer::AttachRenderer(opKey, mc_pmatLocal);
ForEachParticleRendering(obj);
}
}
else if (m_pParticleProperty->m_byBillboardType == BILLBOARD_TYPE_2FACE)
{
if (!m_pParticleProperty->m_bAttachFlag)
{
auto obj = NParticleRenderer::TwoSideRenderer(opKey);
ForEachParticleRendering(obj);
}
else
{
auto obj = NParticleRenderer::TwoSideRenderer(opKey, mc_pmatLocal);
ForEachParticleRendering(obj);
}
}
else if (m_pParticleProperty->m_byBillboardType == BILLBOARD_TYPE_3FACE)
{
if (!m_pParticleProperty->m_bAttachFlag)
{
auto obj = NParticleRenderer::ThreeSideRenderer(opKey);
ForEachParticleRendering(obj);
}
else
{
auto obj = NParticleRenderer::ThreeSideRenderer(opKey, mc_pmatLocal);
ForEachParticleRendering(obj); ForEachParticleRendering(obj);
} }
} }

View File

@@ -1,4 +1,5 @@
#pragma once #pragma once
#include "UserInterface/Locale_inc.h"
#include "EffectElementBaseInstance.h" #include "EffectElementBaseInstance.h"
#include "ParticleInstance.h" #include "ParticleInstance.h"
#include "ParticleProperty.h" #include "ParticleProperty.h"
@@ -25,14 +26,12 @@ class CParticleSystemInstance : public CEffectElementBaseInstance
DWORD dwFrameIndex; DWORD dwFrameIndex;
for(dwFrameIndex=0; dwFrameIndex<m_kVct_pkImgInst.size(); dwFrameIndex++) for(dwFrameIndex=0; dwFrameIndex<m_kVct_pkImgInst.size(); dwFrameIndex++)
{ {
STATEMANAGER.SetTexture(0, m_kVct_pkImgInst[dwFrameIndex]->GetTextureReference().GetD3DTexture());
TParticleInstanceList::iterator itor = m_ParticleInstanceListVector[dwFrameIndex].begin(); TParticleInstanceList::iterator itor = m_ParticleInstanceListVector[dwFrameIndex].begin();
for (; itor != m_ParticleInstanceListVector[dwFrameIndex].end(); ++itor) for (; itor != m_ParticleInstanceListVector[dwFrameIndex].end(); ++itor)
{ {
if (!InFrustum(*itor)) if (!InFrustum(*itor))
continue; return;
FunObj(*itor, m_kVct_pkImgInst[dwFrameIndex]->GetTextureReference().GetD3DTexture());
FunObj(*itor);
} }
} }
} }
@@ -58,6 +57,8 @@ class CParticleSystemInstance : public CEffectElementBaseInstance
DWORD GetEmissionCount(); DWORD GetEmissionCount();
void BatchParticles();
protected: protected:
void OnInitialize(); void OnInitialize();
void OnDestroy(); void OnDestroy();

View File

@@ -1,5 +1,5 @@
#include "Stdafx.h" #include "Stdafx.h"
#include "EterLib/GrpLightManager.h" #include "../eterLib/GrpLightManager.h"
#include "SimpleLightInstance.h" #include "SimpleLightInstance.h"

View File

@@ -1,6 +1,6 @@
#pragma once #pragma once
#include "EterLib/GrpScreen.h" #include "../eterLib/GrpScreen.h"
#include "EffectElementBaseInstance.h" #include "EffectElementBaseInstance.h"
#include "SimpleLightData.h" #include "SimpleLightData.h"

View File

@@ -2,19 +2,17 @@
//#include <crtdbg.h> //#include <crtdbg.h>
#include "EterBase/StdAfx.h" #include "../eterBase/StdAfx.h"
#include "EterBase/Utils.h"
#include "EterBase/Timer.h"
#include "EterBase/CRC32.h"
#include "EterBase/Debug.h"
#include "EterLib/StdAfx.h"
#include "EterLib/TextFileLoader.h"
#include "AudioLib/StdAfx.h" #include "../eterBase/Utils.h"
#include "../eterBase/Timer.h"
#include "../eterBase/CRC32.h"
#include "../eterBase/Debug.h"
#include "UserInterface/Locale_inc.h" #include "../eterLib/StdAfx.h"
#include "../eterLib/TextFileLoader.h"
#include "../milesLib/StdAfx.h"
/* /*
#include "FrameController.h" #include "FrameController.h"

View File

@@ -74,8 +74,8 @@ enum EBillBoardType
BILLBOARD_TYPE_LIE, // 바닥에 누은 형상 BILLBOARD_TYPE_LIE, // 바닥에 누은 형상
BILLBOARD_TYPE_2FACE, // / and BILLBOARD_TYPE_2FACE, // / and \
BILLBOARD_TYPE_3FACE, // / and BILLBOARD_TYPE_3FACE, // / and \ and -
//BILLBOARD_TYPE_RAY, // 잔상 //BILLBOARD_TYPE_RAY, // 잔상
@@ -123,6 +123,68 @@ typedef struct SEffectPosition : public CTimeEvent<D3DXVECTOR3>
D3DXVECTOR3 m_vecControlPoint; D3DXVECTOR3 m_vecControlPoint;
} TEffectPosition; } TEffectPosition;
#define AG_MASK 0xff00ff00
#define RB_MASK 0x00ff00ff
struct DWORDCOLOR
{
DWORD m_dwColor;
DWORDCOLOR()
{
}
DWORDCOLOR(const DWORDCOLOR& r)
: m_dwColor(r.m_dwColor)
{
}
DWORDCOLOR(DWORD dwColor)
: m_dwColor(dwColor)
{
}
DWORDCOLOR& operator = (const DWORDCOLOR& r)
{
m_dwColor = r.m_dwColor;
return *this;
}
DWORDCOLOR& operator *= (float f)
{
DWORD idx = DWORD(f * 256);
m_dwColor =
(((DWORD)(((m_dwColor & AG_MASK) >> 8) * idx)) & AG_MASK)
+ ((DWORD)(((m_dwColor & RB_MASK) * idx) >> 8) & RB_MASK);
return *this;
}
DWORDCOLOR& operator += (const DWORDCOLOR& r)
{
m_dwColor += r.m_dwColor;
return *this;
}
operator DWORD()
{
return m_dwColor;
}
};
#undef AG_MASK
#undef RB_MASK
inline DWORDCOLOR operator * (DWORDCOLOR dc, float f)
{
DWORDCOLOR tmp(dc);
tmp *= f;
return tmp;
}
inline DWORDCOLOR operator * (float f, DWORDCOLOR dc)
{
DWORDCOLOR tmp(dc);
tmp *= f;
return tmp;
}
typedef CTimeEvent<char> TTimeEventTypeCharacter; typedef CTimeEvent<char> TTimeEventTypeCharacter;
typedef CTimeEvent<short> TTimeEventTypeShort; typedef CTimeEvent<short> TTimeEventTypeShort;
typedef CTimeEvent<float> TTimeEventTypeFloat; typedef CTimeEvent<float> TTimeEventTypeFloat;
@@ -176,6 +238,14 @@ inline D3DXVECTOR3 BlendSingleValue(float time, const TEffectPosition& low, cons
return D3DXVECTOR3(); return D3DXVECTOR3();
} }
inline DWORDCOLOR BlendSingleValue(float time, const TTimeEventTypeColor& low, const TTimeEventTypeColor& high)
{
const float timeDiff = high.m_fTime - low.m_fTime;
const float perc = (time - low.m_fTime) / timeDiff;
return low.m_Value * (1.0f - perc) + high.m_Value * perc;
}
template <typename T> template <typename T>
auto GetTimeEventBlendValue(float time, auto GetTimeEventBlendValue(float time,
const std::vector<T>& vec) -> typename T::value_type const std::vector<T>& vec) -> typename T::value_type

View File

@@ -5,7 +5,6 @@ add_library(EterBase STATIC ${FILE_SOURCES})
target_link_libraries(EterBase target_link_libraries(EterBase
lzo2 lzo2
cryptopp-static cryptopp-static
mio
) )
GroupSourcesByFolder(EterBase) GroupSourcesByFolder(EterBase)

299
src/EterBase/CPostIt.cpp Normal file
View File

@@ -0,0 +1,299 @@
#include "StdAfx.h"
#include "CPostIt.h"
#include "../eterBase/utils.h"
class _CPostItMemoryBlock
{
public:
_CPostItMemoryBlock( void );
~_CPostItMemoryBlock( void );
BOOL Assign( HANDLE hBlock );
HANDLE CreateHandle( void );
BOOL DestroyHandle( void );
LPSTR Find( LPCSTR lpszKeyName );
BOOL Put( LPCSTR lpBuffer );
BOOL Put( LPCSTR lpszKeyName, LPCSTR lpBuffer );
BOOL Get( LPCSTR lpszKeyName, LPSTR lpBuffer, DWORD nSize );
protected:
typedef std::list<CHAR *> StrList;
typedef StrList::iterator StrListItr;
HANDLE m_hHandle;
StrList m_StrList;
};
CPostIt::CPostIt( LPCSTR szAppName ) : m_pMemoryBlock(NULL), m_bModified(FALSE)
{
Init( szAppName );
}
CPostIt::~CPostIt( void )
{
Destroy();
}
BOOL CPostIt::Init( LPCSTR szAppName )
{
if( szAppName == NULL || !*szAppName ) {
strcpy( m_szClipFormatName, "YMCF" );
} else {
strcpy( m_szClipFormatName, "YMCF_" );
strcat( m_szClipFormatName, szAppName );
}
return TRUE;
}
BOOL CPostIt::CopyTo( CPostIt *pPostIt, LPCSTR lpszKeyName )
{
if( m_pMemoryBlock == NULL )
return FALSE;
LPSTR szText = m_pMemoryBlock->Find( lpszKeyName );
if( szText == NULL )
return FALSE;
return pPostIt->Set( szText );
}
BOOL CPostIt::Flush( void )
{
if( m_bModified == FALSE )
return FALSE;
if( m_pMemoryBlock == NULL )
return FALSE;
UINT uDGPFormat;
uDGPFormat = ::RegisterClipboardFormatA( m_szClipFormatName );
if( ::OpenClipboard( NULL ) == FALSE )
return FALSE;
if( ::SetClipboardData( uDGPFormat, m_pMemoryBlock->CreateHandle() ) == NULL ) {
// DWORD dwLastError = ::GetLastError();
m_pMemoryBlock->DestroyHandle();
::CloseClipboard();
m_bModified = FALSE;
return FALSE;
}
::CloseClipboard();
m_bModified = FALSE;
return TRUE;
}
void CPostIt::Empty( void )
{
SAFE_DELETE( m_pMemoryBlock );
UINT uDGPFormat;
uDGPFormat = ::RegisterClipboardFormatA( m_szClipFormatName );
if( ::OpenClipboard( NULL ) == FALSE )
return;
HANDLE hClipboardMemory = ::GetClipboardData( uDGPFormat );
if( hClipboardMemory ) {
// ::GlobalFree( hClipboardMemory );
::SetClipboardData( uDGPFormat, NULL );
}
::CloseClipboard();
m_bModified = FALSE;
}
void CPostIt::Destroy( void )
{
Flush();
SAFE_DELETE( m_pMemoryBlock );
}
BOOL CPostIt::Set( LPCSTR lpszKeyName, LPCSTR lpBuffer )
{
if( m_pMemoryBlock == NULL )
m_pMemoryBlock = new _CPostItMemoryBlock;
m_pMemoryBlock->Put( lpszKeyName, lpBuffer );
m_bModified = TRUE;
return TRUE;
}
BOOL CPostIt::Set( LPCSTR lpszKeyName, DWORD dwValue )
{
CHAR szValue[12];
_snprintf( szValue, 12, "%d", dwValue );
return Set( lpszKeyName, szValue );
}
BOOL CPostIt::Set( LPCSTR lpBuffer )
{
if( lpBuffer == NULL )
return FALSE;
if( m_pMemoryBlock == NULL )
m_pMemoryBlock = new _CPostItMemoryBlock;
m_pMemoryBlock->Put( lpBuffer );
m_bModified = TRUE;
return TRUE;
}
BOOL CPostIt::Get( LPCSTR lpszKeyName, LPSTR lpBuffer, DWORD nSize )
{
if( m_pMemoryBlock == NULL ) {
UINT uDGPFormat;
uDGPFormat = ::RegisterClipboardFormatA( m_szClipFormatName );
if( ::OpenClipboard( NULL ) == FALSE )
return FALSE;
HANDLE hClipboardMemory = ::GetClipboardData( uDGPFormat );
if( hClipboardMemory == NULL ) {
::CloseClipboard();
return FALSE;
}
m_pMemoryBlock = new _CPostItMemoryBlock;
m_pMemoryBlock->Assign( hClipboardMemory );
::CloseClipboard();
}
return m_pMemoryBlock->Get( lpszKeyName, lpBuffer, nSize );
}
_CPostItMemoryBlock::_CPostItMemoryBlock( void ) : m_hHandle( NULL )
{
}
_CPostItMemoryBlock::~_CPostItMemoryBlock( void )
{
for( StrListItr itr = m_StrList.begin(); itr != m_StrList.end(); ) {
LPSTR lpszText = *itr;
SAFE_DELETE_ARRAY( lpszText );
itr = m_StrList.erase( itr );
}
}
BOOL _CPostItMemoryBlock::Assign( HANDLE hBlock )
{
if( hBlock == NULL || hBlock == INVALID_HANDLE_VALUE )
return FALSE;
LPBYTE lpBuffer = (LPBYTE) ::GlobalLock( hBlock );
if( lpBuffer == NULL )
return FALSE;
DWORD dwCount = *((LPDWORD) lpBuffer); lpBuffer += sizeof( DWORD );
for( DWORD dwI=0; dwI < dwCount; dwI++ ) {
WORD wLen = *((LPWORD) lpBuffer); lpBuffer += sizeof( WORD );
LPSTR lpszText = new CHAR[ wLen + 1 ];
::CopyMemory( lpszText, lpBuffer, wLen );
lpszText[ wLen ] = '\0';
lpBuffer += wLen;
Put( lpszText );
}
::GlobalUnlock( hBlock );
return TRUE;
}
HANDLE _CPostItMemoryBlock::CreateHandle( void )
{
if( m_StrList.size() == 0 )
return INVALID_HANDLE_VALUE;
DWORD dwBlockSize = sizeof( DWORD );
StrListItr itr;
// Calculation for Memory Block Size
for( itr = m_StrList.begin(); itr != m_StrList.end(); ++itr ) {
dwBlockSize += sizeof( WORD );
dwBlockSize += (DWORD) strlen( *itr );
}
HANDLE hBlock = ::GlobalAlloc( GMEM_ZEROINIT | GMEM_MOVEABLE, dwBlockSize );
if( hBlock == NULL )
return INVALID_HANDLE_VALUE;
LPBYTE lpBuffer = (LPBYTE) ::GlobalLock( hBlock );
if( lpBuffer == NULL ) {
::GlobalFree( hBlock );
return INVALID_HANDLE_VALUE;
}
*((LPDWORD) lpBuffer) = (DWORD) m_StrList.size(); lpBuffer += sizeof( DWORD );
for( itr = m_StrList.begin(); itr != m_StrList.end(); ++itr ) {
*((LPWORD) lpBuffer) = (WORD) strlen( *itr ); lpBuffer += sizeof( WORD );
::CopyMemory( lpBuffer, *itr, strlen( *itr ) ); lpBuffer += strlen( *itr );
}
::GlobalUnlock( hBlock );
m_hHandle = hBlock;
return hBlock;
}
BOOL _CPostItMemoryBlock::DestroyHandle( void )
{
::GlobalFree( m_hHandle );
m_hHandle = NULL;
return TRUE;
}
LPSTR _CPostItMemoryBlock::Find( LPCSTR lpszKeyName )
{
for( StrListItr itr = m_StrList.begin(); itr != m_StrList.end(); ++itr ) {
LPSTR lpszText = *itr;
if( _strnicmp( lpszText, lpszKeyName, strlen( lpszKeyName ) ) != 0 )
continue;
if( *(lpszText + strlen( lpszKeyName )) != '=' )
continue;
return lpszText;
}
return NULL;
}
BOOL _CPostItMemoryBlock::Put( LPCSTR lpszKeyName, LPCSTR lpBuffer )
{
LPSTR lpszText;
if( (lpszText = Find( lpszKeyName )) != NULL ) {
for( StrListItr itr = m_StrList.begin(); itr != m_StrList.end(); ++itr ) {
if( lpszText == *itr ) {
SAFE_DELETE_ARRAY( lpszText );
m_StrList.erase( itr );
break;
}
}
}
if( lpBuffer == NULL || !*lpBuffer )
return TRUE;
size_t nStrLen = strlen( lpszKeyName ) + 1 /* '=' */ + strlen( lpBuffer );
lpszText = new CHAR[ nStrLen + 1 ];
::CopyMemory( lpszText, lpszKeyName, strlen( lpszKeyName ) );
*(lpszText + strlen( lpszKeyName )) = '=';
::CopyMemory( lpszText + strlen( lpszKeyName ) + 1, lpBuffer, strlen( lpBuffer ) );
*(lpszText + nStrLen) = '\0';
m_StrList.push_back( lpszText );
return TRUE;
}
BOOL _CPostItMemoryBlock::Put( LPCSTR lpBuffer )
{
LPSTR lpszText;
if( lpBuffer == NULL || !*lpBuffer )
return TRUE;
size_t nStrLen = strlen( lpBuffer );
lpszText = new CHAR[ nStrLen + 1 ];
::CopyMemory( lpszText, lpBuffer, nStrLen );
*(lpszText + nStrLen) = '\0';
m_StrList.push_back( lpszText );
return TRUE;
}
BOOL _CPostItMemoryBlock::Get( LPCSTR lpszKeyName, LPSTR lpBuffer, DWORD nSize )
{
LPSTR lpszText = Find( lpszKeyName );
if( lpszText == NULL )
return FALSE;
lpszText += (strlen( lpszKeyName ) + 1);
::ZeroMemory( lpBuffer, nSize );
strncpy( lpBuffer, lpszText, (nSize < strlen( lpszText )) ? nSize : strlen( lpszText ) );
return TRUE;
}

80
src/EterBase/CPostIt.h Normal file
View File

@@ -0,0 +1,80 @@
#ifndef _EL_CPOSTIT_H_
#define _EL_CPOSTIT_H_
// _CPostItMemoryBlock is defined in CPostIt.cpp
class _CPostItMemoryBlock;
/**
* @class CPostIt
* @brief 게임런처에서 게임 클라이언트로 정보를 전달 및 클라이언트에서 수신하기 위하여 사용되는 클래스
*/
class CPostIt
{
public:
/**
* @brief CPostIt constructor
* @param [in] szAppName : 게임의 이름이 들어간다.
*/
explicit CPostIt( LPCSTR szAppName );
/**
* @brief CPostIt destructor
*/
~CPostIt( void );
/**
* @brief CPostIt class에서 보유하고 있는 데이타를 클립보드에 저장한다.
*/
BOOL Flush( void );
/**
* @brief CPostIt class에서 보유하고 있는 데이타 및 클립보드에 있는 내용을 지운다.
*/
void Empty( void );
/**
* @brief 데이타를 읽어온다.
* @param [in] lpszKeyName : 불러올 데이타의 키. "KEY" 식의 내용을 넣는다.
* @param [in] lpszData : 불러올 데이타의 버퍼
* @param [in] nSize : lpszData 버퍼의 최대사이즈
*/
BOOL Get( LPCSTR lpszKeyName, LPSTR lpszData, DWORD nSize );
/**
* @brief 저장할 데이타를 넣는다.
* @param [in] lpBuffer : 저장할 데이타. "KEY=DATA" 식의 내용을 넣는다.
*/
BOOL Set( LPCSTR lpszData );
/**
* @brief 저장할 데이타를 넣는다.
* @param [in] lpszKeyName : 저장할 데이타의 키. "KEY" 식의 내용을 넣는다.
* @param [in] lpszData : 저장할 데이타. "DATA" 식의 내용을 넣는다.
*/
BOOL Set( LPCSTR lpszKeyName, LPCSTR lpszData );
/**
* @brief 저장할 데이타(DWORD)를 넣는다.
* @param [in] lpBuffer : 저장할 데이타. "KEY=DATA" 식의 데이타를 넣는다.
* @param [in] dwValue : 저장할 데이타. (DWORD)
*/
BOOL Set( LPCSTR lpszKeyName, DWORD dwValue );
/**
* @brief CPostIt class를 복사한다. (클래스 constructor에 이름 인자가 있기 때문에, 새 이름을 지정해야함)
* @param [in] pPostIt : Destination class
* @param [in] lpszKeyName : Destination class's new app-name
*/
BOOL CopyTo( CPostIt *pPostIt, LPCSTR lpszKeyName );
protected:
BOOL Init( LPCSTR szAppName );
void Destroy( void );
protected:
BOOL m_bModified;
CHAR m_szClipFormatName[_MAX_PATH];
_CPostItMemoryBlock* m_pMemoryBlock;
};
#endif /* _EL_CPOSTIT_H_ */

View File

@@ -1,8 +1,6 @@
#include "StdAfx.h" #include "StdAfx.h"
#include "CRC32.h" #include "CRC32.h"
#include <utf8.h>
static unsigned long CRCTable[256] = static unsigned long CRCTable[256] =
{ {
0x00000000,0x77073096,0xEE0E612C,0x990951BA,0x076DC419,0x706AF48F, 0x00000000,0x77073096,0xEE0E612C,0x990951BA,0x076DC419,0x706AF48F,
@@ -149,55 +147,65 @@ DWORD GetHFILECRC32(HANDLE hFile)
dataOffset + mapSize, // low dataOffset + mapSize, // low
NULL); // name NULL); // name
if (hFM) if (hFM)
{ {
LPVOID lpMapData = MapViewOfFile(hFM, FILE_MAP_READ, 0, dwFileMapStart, dwMapViewSize); LPVOID lpMapData = MapViewOfFile(hFM,
FILE_MAP_READ,
0,
dwFileMapStart,
dwMapViewSize);
dwRetCRC32=GetCRC32((const char*)lpMapData, dwFileSize);
if (lpMapData) if (lpMapData)
{ {
//tw1x1: If MapViewOfFile returns null, crash risk on mapping failure
dwRetCRC32 = GetCRC32((const char*)lpMapData, dwFileSize);
UnmapViewOfFile(lpMapData); UnmapViewOfFile(lpMapData);
} }
CloseHandle(hFM); CloseHandle(hFM);
} }
return dwRetCRC32; return dwRetCRC32;
} }
DWORD GetFileCRC32(const wchar_t* c_szFileName) DWORD GetFileCRC32(const char* c_szFileName)
{ {
if (!c_szFileName || !*c_szFileName) HANDLE hFile = CreateFile(c_szFileName, // name of the file
GENERIC_READ, // desired access
FILE_SHARE_READ, // share mode
NULL, // security attributes
OPEN_EXISTING, // creation disposition
FILE_ATTRIBUTE_NORMAL, // flags and attr
NULL); // template file
if (INVALID_HANDLE_VALUE == hFile)
return 0; return 0;
HANDLE hFile = CreateFileW(c_szFileName, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
if (hFile == INVALID_HANDLE_VALUE) DWORD dwRetCRC32=GetHFILECRC32(hFile);
return 0;
DWORD dwRetCRC32 = GetHFILECRC32(hFile);
CloseHandle(hFile); CloseHandle(hFile);
return dwRetCRC32; return dwRetCRC32;
} }
DWORD GetFileCRC32(const char* fileUtf8)
{
if (!fileUtf8 || !*fileUtf8)
return 0;
std::wstring wFile = Utf8ToWide(fileUtf8);
return GetFileCRC32(wFile.c_str());
}
DWORD GetFileSize(const char* c_szFileName) DWORD GetFileSize(const char* c_szFileName)
{ {
if (!c_szFileName || !*c_szFileName) HANDLE hFile = CreateFile(c_szFileName, // name of the file
GENERIC_READ, // desired access
FILE_SHARE_READ, // share mode
NULL, // security attributes
OPEN_EXISTING, // creation disposition
FILE_ATTRIBUTE_NORMAL, // flags and attr
NULL); // template file
if (INVALID_HANDLE_VALUE == hFile)
return 0; return 0;
std::wstring wFile = Utf8ToWide(std::string(c_szFileName)); DWORD dwSize = GetFileSize(hFile, NULL);
HANDLE hFile = CreateFileW(wFile.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
if (hFile == INVALID_HANDLE_VALUE)
return 0;
DWORD dwSize = ::GetFileSize(hFile, nullptr);
CloseHandle(hFile); CloseHandle(hFile);
return dwSize; return dwSize;
} }

View File

@@ -6,8 +6,7 @@
DWORD GetCRC32(const char* buffer, size_t count); DWORD GetCRC32(const char* buffer, size_t count);
DWORD GetCaseCRC32(const char * buf, size_t len); DWORD GetCaseCRC32(const char * buf, size_t len);
DWORD GetHFILECRC32(HANDLE hFile); DWORD GetHFILECRC32(HANDLE hFile);
DWORD GetFileCRC32(const wchar_t* c_szFileName); DWORD GetFileCRC32(const char* c_szFileName);
DWORD GetFileCRC32(const char* fileUtf8);
DWORD GetFileSize(const char* c_szFileName); DWORD GetFileSize(const char* c_szFileName);
#endif #endif

View File

@@ -2,266 +2,237 @@
#include <time.h> #include <time.h>
#include <stdio.h> #include <stdio.h>
#include <stdarg.h>
#include <string>
#include "Debug.h" #include "Debug.h"
#include "Singleton.h" #include "Singleton.h"
#include "Timer.h" #include "Timer.h"
#include <filesystem>
#include <utf8.h>
const DWORD DEBUG_STRING_MAX_LEN = 1024; const DWORD DEBUG_STRING_MAX_LEN = 1024;
static int isLogFile = false; static int isLogFile = false;
HWND g_PopupHwnd = NULL; HWND g_PopupHwnd = NULL;
// Convert UTF-8 char* -> wide and send to debugger (NO helper function, just a macro)
#ifdef _DEBUG
#define DBG_OUT_W_UTF8(psz) \
do { \
const char* __s = (psz) ? (psz) : ""; \
std::wstring __w = Utf8ToWide(__s); \
OutputDebugStringW(__w.c_str()); \
} while (0)
#else
#define DBG_OUT_W_UTF8(psz) do { (void)(psz); } while (0)
#endif
class CLogFile : public CSingleton<CLogFile> class CLogFile : public CSingleton<CLogFile>
{ {
public: public:
CLogFile() : m_fp(NULL) {} CLogFile() : m_fp(NULL)
{
}
virtual ~CLogFile() virtual ~CLogFile()
{ {
if (m_fp) if (m_fp)
fclose(m_fp); fclose(m_fp);
m_fp = NULL; m_fp = NULL;
} }
void Initialize() void Initialize()
{ {
m_fp = fopen("log/log.txt", "w"); m_fp = fopen("log.txt", "w");
} }
void Write(const char* c_pszMsg) void Write(const char * c_pszMsg)
{ {
if (!m_fp) if (!m_fp)
return; return;
time_t ct = time(0); time_t ct = time(0);
struct tm ctm = *localtime(&ct); struct tm ctm = *localtime(&ct);
fprintf(m_fp, "%02d%02d %02d:%02d:%05d :: %s", fprintf(m_fp, "%02d%02d %02d:%02d:%05d :: %s",
ctm.tm_mon + 1, ctm.tm_mon + 1,
ctm.tm_mday, ctm.tm_mday,
ctm.tm_hour, ctm.tm_hour,
ctm.tm_min, ctm.tm_min,
ELTimer_GetMSec() % 60000, ELTimer_GetMSec() % 60000,
c_pszMsg); c_pszMsg);
fflush(m_fp); fflush(m_fp);
} }
protected: protected:
FILE* m_fp; FILE * m_fp;
}; };
static CLogFile gs_logfile; static CLogFile gs_logfile;
static UINT gs_uLevel = 0; static UINT gs_uLevel=0;
void SetLogLevel(UINT uLevel) void SetLogLevel(UINT uLevel)
{ {
gs_uLevel = uLevel; gs_uLevel=uLevel;
} }
void Log(UINT uLevel, const char* c_szMsg) void Log(UINT uLevel, const char* c_szMsg)
{ {
if (uLevel >= gs_uLevel) if (uLevel>=gs_uLevel)
Trace(c_szMsg); Trace(c_szMsg);
} }
void Logn(UINT uLevel, const char* c_szMsg) void Logn(UINT uLevel, const char* c_szMsg)
{ {
if (uLevel >= gs_uLevel) if (uLevel>=gs_uLevel)
Tracen(c_szMsg); Tracen(c_szMsg);
} }
void Logf(UINT uLevel, const char* c_szFormat, ...) void Logf(UINT uLevel, const char* c_szFormat, ...)
{ {
if (uLevel < gs_uLevel) if (uLevel<gs_uLevel)
return; return;
char szBuf[DEBUG_STRING_MAX_LEN + 1]; char szBuf[DEBUG_STRING_MAX_LEN+1];
va_list args;
va_start(args, c_szFormat);
_vsnprintf_s(szBuf, sizeof(szBuf), _TRUNCATE, c_szFormat, args);
va_end(args);
va_list args;
va_start(args, c_szFormat);
_vsnprintf(szBuf, sizeof(szBuf), c_szFormat, args);
va_end(args);
#ifdef _DEBUG #ifdef _DEBUG
DBG_OUT_W_UTF8(szBuf); OutputDebugString(szBuf);
fputs(szBuf, stdout); fputs(szBuf, stdout);
#endif #endif
if (isLogFile) if (isLogFile)
LogFile(szBuf); LogFile(szBuf);
} }
void Lognf(UINT uLevel, const char* c_szFormat, ...) void Lognf(UINT uLevel, const char* c_szFormat, ...)
{ {
if (uLevel < gs_uLevel) if (uLevel<gs_uLevel)
return; return;
char szBuf[DEBUG_STRING_MAX_LEN + 2]; va_list args;
va_start(args, c_szFormat);
va_list args; char szBuf[DEBUG_STRING_MAX_LEN+2];
va_start(args, c_szFormat); int len = _vsnprintf(szBuf, sizeof(szBuf)-1, c_szFormat, args);
_vsnprintf_s(szBuf, sizeof(szBuf), _TRUNCATE, c_szFormat, args);
va_end(args);
size_t cur = strnlen(szBuf, sizeof(szBuf));
if (cur + 1 < sizeof(szBuf)) {
szBuf[cur] = '\n';
szBuf[cur + 1] = '\0';
}
else {
szBuf[sizeof(szBuf) - 2] = '\n';
szBuf[sizeof(szBuf) - 1] = '\0';
}
if (len > 0)
{
szBuf[len] = '\n';
szBuf[len + 1] = '\0';
}
va_end(args);
#ifdef _DEBUG #ifdef _DEBUG
DBG_OUT_W_UTF8(szBuf); OutputDebugString(szBuf);
fputs(szBuf, stdout); puts(szBuf);
#endif #endif
if (isLogFile) if (isLogFile)
LogFile(szBuf); LogFile(szBuf);
} }
void Trace(const char* c_szMsg)
void Trace(const char * c_szMsg)
{ {
#ifdef _DEBUG #ifdef _DEBUG
DBG_OUT_W_UTF8(c_szMsg); OutputDebugString(c_szMsg);
printf("%s", c_szMsg ? c_szMsg : ""); printf("%s", c_szMsg);
#endif #endif
if (isLogFile) if (isLogFile)
LogFile(c_szMsg ? c_szMsg : ""); LogFile(c_szMsg);
} }
void Tracen(const char* c_szMsg) void Tracen(const char* c_szMsg)
{ {
#ifdef _DEBUG #ifdef _DEBUG
char szBuf[DEBUG_STRING_MAX_LEN + 2]; char szBuf[DEBUG_STRING_MAX_LEN+1];
_snprintf_s(szBuf, sizeof(szBuf), _TRUNCATE, "%s\n", c_szMsg ? c_szMsg : ""); _snprintf(szBuf, sizeof(szBuf), "%s\n", c_szMsg);
OutputDebugString(szBuf);
puts(c_szMsg);
DBG_OUT_W_UTF8(szBuf); if (isLogFile)
LogFile(szBuf);
fputs(szBuf, stdout); puts(c_szMsg);
putc('\n', stdout);
if (isLogFile)
LogFile(szBuf);
#else #else
if (isLogFile) if (isLogFile)
{ {
LogFile(c_szMsg ? c_szMsg : ""); LogFile(c_szMsg);
LogFile("\n"); LogFile("\n");
} }
#endif #endif
} }
void Tracenf(const char* c_szFormat, ...) void Tracenf(const char* c_szFormat, ...)
{ {
char szBuf[DEBUG_STRING_MAX_LEN + 2]; va_list args;
va_start(args, c_szFormat);
va_list args; char szBuf[DEBUG_STRING_MAX_LEN+2];
va_start(args, c_szFormat); int len = _vsnprintf(szBuf, sizeof(szBuf)-1, c_szFormat, args);
_vsnprintf_s(szBuf, sizeof(szBuf), _TRUNCATE, c_szFormat, args);
va_end(args);
size_t cur = strnlen(szBuf, sizeof(szBuf));
if (cur + 1 < sizeof(szBuf)) {
szBuf[cur] = '\n';
szBuf[cur + 1] = '\0';
}
else {
szBuf[sizeof(szBuf) - 2] = '\n';
szBuf[sizeof(szBuf) - 1] = '\0';
}
if (len > 0)
{
szBuf[len] = '\n';
szBuf[len + 1] = '\0';
}
va_end(args);
#ifdef _DEBUG #ifdef _DEBUG
DBG_OUT_W_UTF8(szBuf); OutputDebugString(szBuf);
fputs(szBuf, stdout); printf("%s", szBuf);
#endif #endif
if (isLogFile) if (isLogFile)
LogFile(szBuf); LogFile(szBuf);
} }
void Tracef(const char* c_szFormat, ...) void Tracef(const char* c_szFormat, ...)
{ {
char szBuf[DEBUG_STRING_MAX_LEN + 1]; char szBuf[DEBUG_STRING_MAX_LEN+1];
va_list args; va_list args;
va_start(args, c_szFormat); va_start(args, c_szFormat);
_vsnprintf_s(szBuf, sizeof(szBuf), _TRUNCATE, c_szFormat, args); _vsnprintf(szBuf, sizeof(szBuf), c_szFormat, args);
va_end(args); va_end(args);
#ifdef _DEBUG #ifdef _DEBUG
DBG_OUT_W_UTF8(szBuf); OutputDebugString(szBuf);
fputs(szBuf, stdout); fputs(szBuf, stdout);
#endif #endif
if (isLogFile) if (isLogFile)
LogFile(szBuf); LogFile(szBuf);
} }
void TraceError(const char* c_szFormat, ...) void TraceError(const char* c_szFormat, ...)
{ {
#ifndef _DISTRIBUTE #ifndef _DISTRIBUTE
char szBuf[DEBUG_STRING_MAX_LEN + 2];
strncpy_s(szBuf, sizeof(szBuf), "SYSERR: ", _TRUNCATE); char szBuf[DEBUG_STRING_MAX_LEN+2];
int prefixLen = (int)strlen(szBuf);
va_list args; strncpy(szBuf, "SYSERR: ", DEBUG_STRING_MAX_LEN);
va_start(args, c_szFormat); int len = strlen(szBuf);
_vsnprintf_s(szBuf + prefixLen, sizeof(szBuf) - prefixLen, _TRUNCATE, c_szFormat, args);
va_end(args);
size_t cur = strnlen(szBuf, sizeof(szBuf)); va_list args;
if (cur + 1 < sizeof(szBuf)) { va_start(args, c_szFormat);
szBuf[cur] = '\n'; len = _vsnprintf(szBuf + len, sizeof(szBuf) - (len + 1), c_szFormat, args) + len;
szBuf[cur + 1] = '\0'; va_end(args);
}
else {
szBuf[sizeof(szBuf) - 2] = '\n';
szBuf[sizeof(szBuf) - 1] = '\0';
}
time_t ct = time(0); szBuf[len] = '\n';
struct tm ctm = *localtime(&ct); szBuf[len + 1] = '\0';
fprintf(stderr, "%02d%02d %02d:%02d:%05d :: %s", time_t ct = time(0);
ctm.tm_mon + 1, struct tm ctm = *localtime(&ct);
ctm.tm_mday,
ctm.tm_hour,
ctm.tm_min,
ELTimer_GetMSec() % 60000,
szBuf + 8);
fflush(stderr);
fprintf(stderr, "%02d%02d %02d:%02d:%05d :: %s",
ctm.tm_mon + 1,
ctm.tm_mday,
ctm.tm_hour,
ctm.tm_min,
ELTimer_GetMSec() % 60000,
szBuf + 8);
fflush(stderr);
#ifdef _DEBUG #ifdef _DEBUG
DBG_OUT_W_UTF8(szBuf); OutputDebugString(szBuf);
fputs(szBuf, stdout); fputs(szBuf, stdout);
#endif #endif
if (isLogFile) if (isLogFile)
LogFile(szBuf); LogFile(szBuf);
#endif #endif
} }
@@ -269,101 +240,87 @@ void TraceErrorWithoutEnter(const char* c_szFormat, ...)
{ {
#ifndef _DISTRIBUTE #ifndef _DISTRIBUTE
char szBuf[DEBUG_STRING_MAX_LEN]; char szBuf[DEBUG_STRING_MAX_LEN];
va_list args; va_list args;
va_start(args, c_szFormat); va_start(args, c_szFormat);
_vsnprintf_s(szBuf, sizeof(szBuf), _TRUNCATE, c_szFormat, args); _vsnprintf(szBuf, sizeof(szBuf), c_szFormat, args);
va_end(args); va_end(args);
time_t ct = time(0); time_t ct = time(0);
struct tm ctm = *localtime(&ct); struct tm ctm = *localtime(&ct);
fprintf(stderr, "%02d%02d %02d:%02d:%05d :: %s", fprintf(stderr, "%02d%02d %02d:%02d:%05d :: %s",
ctm.tm_mon + 1, ctm.tm_mon + 1,
ctm.tm_mday, ctm.tm_mday,
ctm.tm_hour, ctm.tm_hour,
ctm.tm_min, ctm.tm_min,
ELTimer_GetMSec() % 60000, ELTimer_GetMSec() % 60000,
szBuf + 8); szBuf + 8);
fflush(stderr); fflush(stderr);
#ifdef _DEBUG #ifdef _DEBUG
DBG_OUT_W_UTF8(szBuf); OutputDebugString(szBuf);
fputs(szBuf, stdout); fputs(szBuf, stdout);
#endif #endif
if (isLogFile) if (isLogFile)
LogFile(szBuf); LogFile(szBuf);
#endif #endif
} }
void LogBoxf(const char* c_szFormat, ...) void LogBoxf(const char* c_szFormat, ...)
{ {
va_list args; va_list args;
va_start(args, c_szFormat); va_start(args, c_szFormat);
char szBuf[2048]; char szBuf[2048];
_vsnprintf_s(szBuf, sizeof(szBuf), _TRUNCATE, c_szFormat, args); _vsnprintf(szBuf, sizeof(szBuf), c_szFormat, args);
va_end(args); LogBox(szBuf);
LogBox(szBuf);
} }
void LogBox(const char* c_szMsg, const char* c_szCaption, HWND hWnd) void LogBox(const char* c_szMsg, const char * c_szCaption, HWND hWnd)
{ {
if (!hWnd) if (!hWnd)
hWnd = g_PopupHwnd; hWnd = g_PopupHwnd;
std::wstring wMsg = Utf8ToWide(c_szMsg ? c_szMsg : ""); MessageBox(hWnd, c_szMsg, c_szCaption ? c_szCaption : "LOG", MB_OK);
std::wstring wCaption = Utf8ToWide(c_szCaption ? c_szCaption : "LOG"); Tracen(c_szMsg);
MessageBoxW(hWnd, wMsg.c_str(), wCaption.c_str(), MB_OK);
// Logging stays UTF-8
Tracen(c_szMsg ? c_szMsg : "");
} }
void LogFile(const char* c_szMsg) void LogFile(const char * c_szMsg)
{ {
CLogFile::Instance().Write(c_szMsg); CLogFile::Instance().Write(c_szMsg);
} }
void LogFilef(const char* c_szMessage, ...) void LogFilef(const char * c_szMessage, ...)
{ {
va_list args; va_list args;
va_start(args, c_szMessage); va_start(args, c_szMessage);
char szBuf[DEBUG_STRING_MAX_LEN+1];
_vsnprintf(szBuf, sizeof(szBuf), c_szMessage, args);
char szBuf[DEBUG_STRING_MAX_LEN + 1]; CLogFile::Instance().Write(szBuf);
_vsnprintf_s(szBuf, sizeof(szBuf), _TRUNCATE, c_szMessage, args);
va_end(args);
CLogFile::Instance().Write(szBuf);
} }
void OpenLogFile(bool bUseLogFIle) void OpenLogFile(bool bUseLogFIle)
{ {
if (!std::filesystem::exists("log")) {
std::filesystem::create_directory("log");
}
#ifndef _DISTRIBUTE #ifndef _DISTRIBUTE
_wfreopen(L"log/syserr.txt", L"w", stderr); freopen("syserr.txt", "w", stderr);
if (bUseLogFIle) if (bUseLogFIle)
{ {
isLogFile = true; isLogFile = true;
CLogFile::Instance().Initialize(); CLogFile::Instance().Initialize();
} }
#endif #endif
} }
void OpenConsoleWindow() void OpenConsoleWindow()
{ {
AllocConsole(); AllocConsole();
_wfreopen(L"CONOUT$", L"a", stdout); freopen("CONOUT$", "a", stdout);
_wfreopen(L"CONIN$", L"r", stdin); freopen("CONIN$", "r", stdin);
} }

View File

@@ -38,9 +38,3 @@ extern HWND g_PopupHwnd;
} \ } \
#endif #endif
#if defined(_DEBUG)
#define MD_ASSERT(expr) ((expr) ? true : (TraceError("MD_ASSERT('%s') failed at (%s:%d)", #expr, __FILE__, __LINE__), throw "ffs", false))
#else
#define MD_ASSERT(expr) ((expr) ? true : (TraceError("MD_ASSERT('%s') failed at (%s:%d)", #expr, __FILE__, __LINE__), false))
#endif

View File

@@ -1,8 +1,6 @@
#include "StdAfx.h" #include "StdAfx.h"
#include "FileBase.h" #include "FileBase.h"
#include <utf8.h>
CFileBase::CFileBase() : m_hFile(NULL), m_dwSize(0) CFileBase::CFileBase() : m_hFile(NULL), m_dwSize(0)
{ {
} }
@@ -36,12 +34,9 @@ BOOL CFileBase::Create(const char* filename, EFileMode mode)
{ {
Destroy(); Destroy();
// Keep filename internally as UTF-8 (engine side)
strncpy(m_filename, filename, MAX_PATH); strncpy(m_filename, filename, MAX_PATH);
m_filename[MAX_PATH - 1] = '\0';
DWORD dwMode; DWORD dwMode, dwShareMode = FILE_SHARE_READ;
DWORD dwShareMode = FILE_SHARE_READ;
if (mode == FILEMODE_WRITE) if (mode == FILEMODE_WRITE)
{ {
@@ -49,26 +44,19 @@ BOOL CFileBase::Create(const char* filename, EFileMode mode)
dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
} }
else else
{
dwMode = GENERIC_READ; dwMode = GENERIC_READ;
}
// UTF-8 -> UTF-16 conversion for WinAPI m_hFile = CreateFile(filename, // name of the file
std::wstring wFilename = Utf8ToWide(filename); dwMode, // desired access
dwShareMode, // share mode
m_hFile = CreateFileW( NULL, // security attributes
wFilename.c_str(), // UTF-16 path mode == FILEMODE_READ ? OPEN_EXISTING : OPEN_ALWAYS, // creation disposition
dwMode, FILE_ATTRIBUTE_NORMAL, // flags and attr
dwShareMode, NULL); // template file
nullptr,
(mode == FILEMODE_READ) ? OPEN_EXISTING : OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
nullptr
);
if (m_hFile != INVALID_HANDLE_VALUE) if (m_hFile != INVALID_HANDLE_VALUE)
{ {
m_dwSize = GetFileSize(m_hFile, nullptr); m_dwSize = GetFileSize(m_hFile, NULL);
m_mode = mode; m_mode = mode;
return true; return true;
} }
@@ -76,7 +64,7 @@ BOOL CFileBase::Create(const char* filename, EFileMode mode)
/* char buf[256]; /* char buf[256];
GetCurrentDirectory(256, buf); GetCurrentDirectory(256, buf);
DWORD dwErr = GetLastError();*/ DWORD dwErr = GetLastError();*/
m_hFile = nullptr; m_hFile = NULL;
return false; return false;
} }
@@ -107,7 +95,7 @@ BOOL CFileBase::Write(const void* src, int bytes)
{ {
DWORD dwUseless; DWORD dwUseless;
BOOL ret = WriteFile(m_hFile, src, bytes, &dwUseless, NULL); BOOL ret = WriteFile(m_hFile, src, bytes, &dwUseless, NULL);
if (!ret) if (!ret)
return false; return false;

View File

@@ -1,7 +1,6 @@
#include "StdAfx.h" #include "StdAfx.h"
#include "FileDir.h" #include "FileDir.h"
#include <string> #include <string>
#include <utf8.h>
CDir::CDir() CDir::CDir()
{ {
@@ -21,46 +20,43 @@ void CDir::Destroy()
Initialize(); Initialize();
} }
bool CDir::Create(const char* c_szFilter, const char* c_szPath, BOOL bCheckedExtension) bool CDir::Create(const char * c_szFilter, const char* c_szPath, BOOL bCheckedExtension)
{ {
Destroy(); Destroy();
std::string stPath = c_szPath;
std::string stPath = c_szPath ? c_szPath : ""; if (stPath.length())
if (!stPath.empty())
{ {
char end = stPath.back(); char end = stPath[stPath.length() - 1];
if (end != '\\') if (end != '\\')
stPath += '\\'; stPath+='\\';
} }
// Query: UTF-8 -> UTF-16 for WinAPI std::string stQuery;
std::string stQueryUtf8 = stPath + "*.*"; stQuery += stPath;
std::wstring stQueryW = Utf8ToWide(stQueryUtf8); stQuery += "*.*";
m_wfd.dwFileAttributes = 0;
m_wfd.dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY; m_wfd.dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
m_hFind = FindFirstFile(stQuery.c_str(), &m_wfd);
m_hFind = FindFirstFileW(stQueryW.c_str(), &m_wfd);
if (m_hFind == INVALID_HANDLE_VALUE) if (m_hFind == INVALID_HANDLE_VALUE)
return true; return true;
do do
{ {
// Convert filename to UTF-8 for existing logic/callbacks if (*m_wfd.cFileName == '.')
std::string fileNameUtf8 = WideToUtf8(m_wfd.cFileName);
if (!fileNameUtf8.empty() && fileNameUtf8[0] == '.')
continue; continue;
if (IsFolder()) if (IsFolder())
{ {
if (!OnFolder(c_szFilter, stPath.c_str(), fileNameUtf8.c_str())) if (!OnFolder(c_szFilter, stPath.c_str(), m_wfd.cFileName))
return false; return false;
} }
else else
{ {
const char* c_szExtension = strchr(fileNameUtf8.c_str(), '.'); const char * c_szExtension = strchr(m_wfd.cFileName, '.');
if (!c_szExtension) if (!c_szExtension)
continue; continue;
@@ -69,29 +65,27 @@ bool CDir::Create(const char* c_szFilter, const char* c_szPath, BOOL bCheckedExt
// 그전에 전 프로젝트의 CDir을 사용하는 곳에서 Extension을 "wav", "gr2" 이런식으로 넣게끔 한다. - [levites] // 그전에 전 프로젝트의 CDir을 사용하는 곳에서 Extension을 "wav", "gr2" 이런식으로 넣게끔 한다. - [levites]
if (bCheckedExtension) if (bCheckedExtension)
{ {
std::string strFilter = c_szFilter ? c_szFilter : ""; std::string strFilter = c_szFilter;
int iPos = (int)strFilter.find_first_of(';', 0); int iPos = strFilter.find_first_of(';', 0);
if (iPos > 0) if (iPos > 0)
{ {
std::string first = strFilter.substr(0, iPos); std::string strFirstFilter = std::string(c_szFilter).substr(0, iPos);
std::string second = strFilter.substr(iPos + 1); std::string strSecondFilter = std::string(c_szFilter).substr(iPos+1, strlen(c_szFilter));
if (0 != strFirstFilter.compare(c_szExtension+1) && 0 != strSecondFilter.compare(c_szExtension+1))
if (0 != first.compare(c_szExtension + 1) &&
0 != second.compare(c_szExtension + 1))
continue; continue;
} }
else else
{ {
if (0 != _stricmp(c_szExtension + 1, c_szFilter)) if (0 != stricmp(c_szExtension+1, c_szFilter))
continue; continue;
} }
} }
if (!OnFile(stPath.c_str(), fileNameUtf8.c_str())) if (!OnFile(stPath.c_str(), m_wfd.cFileName))
return false; return false;
} }
} while (FindNextFileW(m_hFind, &m_wfd)); }
while (FindNextFile(m_hFind, &m_wfd));
return true; return true;
} }
@@ -100,12 +94,12 @@ bool CDir::IsFolder()
{ {
if (m_wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) if (m_wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
return true; return true;
return false; return false;
} }
void CDir::Initialize() void CDir::Initialize()
{ {
memset(&m_wfd, 0, sizeof(m_wfd)); memset(&m_wfd, 0, sizeof(m_wfd));
m_hFind = NULL; m_hFind = NULL;
} }

View File

@@ -1,7 +1,6 @@
#include "StdAfx.h" #include "StdAfx.h"
#include "FileLoader.h" #include "FileLoader.h"
#include <assert.h> #include <assert.h>
#include <utf8.h>
CMemoryTextFileLoader::CMemoryTextFileLoader() CMemoryTextFileLoader::CMemoryTextFileLoader()
{ {
@@ -253,9 +252,7 @@ bool CDiskFileLoader::Open(const char* c_szFileName)
if (!c_szFileName[0]) if (!c_szFileName[0])
return false; return false;
// UTF-8 → UTF-16 conversion for Unicode path support m_fp = fopen(c_szFileName, "rb");
std::wstring wFileName = Utf8ToWide(c_szFileName);
m_fp = _wfopen(wFileName.c_str(), L"rb");
if (!m_fp) if (!m_fp)
return false; return false;

259
src/EterBase/MappedFile.cpp Normal file
View File

@@ -0,0 +1,259 @@
#include "StdAfx.h"
#include "MappedFile.h"
#include "Debug.h"
CMappedFile::CMappedFile() :
m_hFM(NULL),
m_lpMapData(NULL),
m_dataOffset(0),
m_mapSize(0),
m_seekPosition(0),
m_pLZObj(NULL),
m_pbBufLinkData(NULL),
m_dwBufLinkSize(0),
m_pbAppendResultDataBlock(NULL),
m_dwAppendResultDataSize(0)
{
}
CMappedFile::~CMappedFile()
{
Destroy();
}
BOOL CMappedFile::Create(const char * filename)
{
Destroy();
return CFileBase::Create(filename, FILEMODE_READ);
}
BOOL CMappedFile::Create(const char * filename, const void** dest, int offset, int size)
{
if (!CMappedFile::Create(filename))
return NULL;
int ret = Map(dest, offset, size);
return (ret) > 0;
}
LPCVOID CMappedFile::Get()
{
return m_lpData;
}
void CMappedFile::Link(DWORD dwBufSize, const void* c_pvBufData)
{
m_dwBufLinkSize=dwBufSize;
m_pbBufLinkData=(BYTE*)c_pvBufData;
}
void CMappedFile::BindLZObject(CLZObject * pLZObj)
{
assert(m_pLZObj == NULL);
m_pLZObj = pLZObj;
Link(m_pLZObj->GetSize(), m_pLZObj->GetBuffer());
}
void CMappedFile::BindLZObjectWithBufferedSize(CLZObject * pLZObj)
{
assert(m_pLZObj == NULL);
m_pLZObj = pLZObj;
Link(m_pLZObj->GetBufferSize(), m_pLZObj->GetBuffer());
}
BYTE* CMappedFile::AppendDataBlock( const void* pBlock, DWORD dwBlockSize )
{
if( m_pbAppendResultDataBlock )
{
delete []m_pbAppendResultDataBlock;
}
//realloc
m_dwAppendResultDataSize = m_dwBufLinkSize+dwBlockSize;
m_pbAppendResultDataBlock = new BYTE[m_dwAppendResultDataSize];
memcpy(m_pbAppendResultDataBlock, m_pbBufLinkData, m_dwBufLinkSize );
memcpy(m_pbAppendResultDataBlock + m_dwBufLinkSize, pBlock, dwBlockSize );
//redirect
Link(m_dwAppendResultDataSize, m_pbAppendResultDataBlock);
return m_pbAppendResultDataBlock;
}
void CMappedFile::Destroy()
{
if (m_pLZObj) // 압축된 데이터가 이 포인터로 연결 된다
{
delete m_pLZObj;
m_pLZObj = NULL;
}
if (NULL != m_lpMapData)
{
Unmap(m_lpMapData);
m_lpMapData = NULL;
}
if (NULL != m_hFM)
{
CloseHandle(m_hFM);
m_hFM = NULL;
}
if( m_pbAppendResultDataBlock )
{
delete []m_pbAppendResultDataBlock;
m_pbAppendResultDataBlock = NULL;
}
m_dwAppendResultDataSize = 0;
m_pbBufLinkData = NULL;
m_dwBufLinkSize = 0;
m_seekPosition = 0;
m_dataOffset = 0;
m_mapSize = 0;
CFileBase::Destroy();
}
int CMappedFile::Seek(DWORD offset, int iSeekType)
{
switch (iSeekType)
{
case SEEK_TYPE_BEGIN:
if (offset > m_dwSize)
offset = m_dwSize;
m_seekPosition = offset;
break;
case SEEK_TYPE_CURRENT:
m_seekPosition = std::min(m_seekPosition + offset, Size());
break;
case SEEK_TYPE_END:
m_seekPosition = std::max(0ul, Size() - offset);
break;
}
return m_seekPosition;
}
// 2004.09.16.myevan.MemoryMappedFile 98/ME 개수 제한 문제 체크
//DWORD g_dwCount=0;
int CMappedFile::Map(const void **dest, int offset, int size)
{
m_dataOffset = offset;
if (size == 0)
m_mapSize = m_dwSize;
else
m_mapSize = size;
if (m_dataOffset + m_mapSize > m_dwSize)
return NULL;
SYSTEM_INFO SysInfo;
GetSystemInfo(&SysInfo);
DWORD dwSysGran = SysInfo.dwAllocationGranularity;
DWORD dwFileMapStart = (m_dataOffset / dwSysGran) * dwSysGran;
DWORD dwMapViewSize = (m_dataOffset % dwSysGran) + m_mapSize;
INT iViewDelta = m_dataOffset - dwFileMapStart;
m_hFM = CreateFileMapping(m_hFile, // handle
NULL, // security
PAGE_READONLY, // flProtect
0, // high
m_dataOffset + m_mapSize, // low
NULL); // name
if (!m_hFM)
{
OutputDebugString("CMappedFile::Map !m_hFM\n");
return NULL;
}
m_lpMapData = MapViewOfFile(m_hFM,
FILE_MAP_READ,
0,
dwFileMapStart,
dwMapViewSize);
if (!m_lpMapData) // Success
{
TraceError("CMappedFile::Map !m_lpMapData %lu", GetLastError());
return 0;
}
// 2004.09.16.myevan.MemoryMappedFile 98/ME 개수 제한 문제 체크
//g_dwCount++;
//Tracenf("MAPFILE %d", g_dwCount);
m_lpData = (char*) m_lpMapData + iViewDelta;
*dest = (char*) m_lpData;
m_seekPosition = 0;
Link(m_mapSize, m_lpData);
return (m_mapSize);
}
BYTE * CMappedFile::GetCurrentSeekPoint()
{
return m_pbBufLinkData+m_seekPosition;
//return m_pLZObj ? m_pLZObj->GetBuffer() + m_seekPosition : (BYTE *) m_lpData + m_seekPosition;
}
DWORD CMappedFile::Size()
{
return m_dwBufLinkSize;
/*
if (m_pLZObj)
return m_pLZObj->GetSize();
return (m_mapSize);
*/
}
DWORD CMappedFile::GetPosition()
{
return m_dataOffset;
}
BOOL CMappedFile::Read(void * dest, int bytes)
{
if (m_seekPosition + bytes > Size())
return FALSE;
memcpy(dest, GetCurrentSeekPoint(), bytes);
m_seekPosition += bytes;
return TRUE;
}
DWORD CMappedFile::GetSeekPosition(void)
{
return m_seekPosition;
}
void CMappedFile::Unmap(LPCVOID data)
{
if (UnmapViewOfFile(data))
{
// 2004.09.16.myevan.MemoryMappedFile 98/ME 개수 제한 문제 체크
//g_dwCount--;
//Tracenf("UNMAPFILE %d", g_dwCount);
}
else
{
TraceError("CMappedFile::Unmap - Error");
}
m_lpData = NULL;
}

59
src/EterBase/MappedFile.h Normal file
View File

@@ -0,0 +1,59 @@
#ifndef __INC_MAPPEDFILE_H__
#define __INC_MAPPEDFILE_H__
#include "lzo.h"
#include "FileBase.h"
class CMappedFile : public CFileBase
{
public:
enum ESeekType
{
SEEK_TYPE_BEGIN,
SEEK_TYPE_CURRENT,
SEEK_TYPE_END
};
public:
CMappedFile();
virtual ~CMappedFile();
void Link(DWORD dwBufSize, const void* c_pvBufData);
BOOL Create(const char* filename);
BOOL Create(const char* filename, const void** dest, int offset, int size);
LPCVOID Get();
void Destroy();
int Seek(DWORD offset, int iSeekType = SEEK_TYPE_BEGIN);
int Map(const void **dest, int offset=0, int size=0);
DWORD Size();
DWORD GetPosition();
BOOL Read(void* dest, int bytes);
DWORD GetSeekPosition();
void BindLZObject(CLZObject * pLZObj);
void BindLZObjectWithBufferedSize(CLZObject * pLZObj);
BYTE* AppendDataBlock( const void* pBlock, DWORD dwBlockSize );
BYTE * GetCurrentSeekPoint();
private:
void Unmap(LPCVOID data);
private:
BYTE* m_pbBufLinkData;
DWORD m_dwBufLinkSize;
BYTE* m_pbAppendResultDataBlock;
DWORD m_dwAppendResultDataSize;
DWORD m_seekPosition;
HANDLE m_hFM;
DWORD m_dataOffset;
DWORD m_mapSize;
LPVOID m_lpMapData;
LPVOID m_lpData;
CLZObject * m_pLZObj;
};
#endif

View File

@@ -0,0 +1,6 @@
#ifndef _EL_SERVICEDEFS_H_
#define _EL_SERVICEDEFS_H_
#define _IMPROVED_PACKET_ENCRYPTION_
#endif //_EL_SERVICEDEFS_H_

View File

@@ -1,5 +1,10 @@
#pragma once #pragma once
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif
#pragma warning(disable:4710) // not inlined #pragma warning(disable:4710) // not inlined
#pragma warning(disable:4786) // character 255 넘어가는거 끄기 #pragma warning(disable:4786) // character 255 넘어가는거 끄기
#pragma warning(disable:4244) // type conversion possible lose of data #pragma warning(disable:4244) // type conversion possible lose of data
@@ -48,5 +53,4 @@
#include "vk.h" #include "vk.h"
#include "filename.h" #include "filename.h"
#include "ServiceDefs.h"
#include "../UserInterface/Locale_inc.h"

View File

@@ -2,17 +2,11 @@
#include "TempFile.h" #include "TempFile.h"
#include "Utils.h" #include "Utils.h"
#include "Debug.h" #include "Debug.h"
#include <utf8.h>
CTempFile::~CTempFile() CTempFile::~CTempFile()
{ {
Destroy(); Destroy();
DeleteFile(m_szFileName);
if (m_szFileName[0])
{
std::wstring wPath = Utf8ToWide(m_szFileName);
DeleteFileW(wPath.c_str());
}
} }
CTempFile::CTempFile(const char * c_pszPrefix) CTempFile::CTempFile(const char * c_pszPrefix)

View File

@@ -5,43 +5,24 @@
#include <io.h> #include <io.h>
#include <assert.h> #include <assert.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <utf8.h>
#include "Utils.h" #include "Utils.h"
#include "filedir.h" #include "filedir.h"
char korean_tolower(const char c); char korean_tolower(const char c);
const char* CreateTempFileName(const char* c_pszPrefix) const char * CreateTempFileName(const char * c_pszPrefix)
{ {
static std::string s_utf8TempName; // safe static storage char szTempPath[MAX_PATH + 1];
static char szTempName[MAX_PATH + 1];
wchar_t wTempPath[MAX_PATH + 1]{}; GetTempPath(MAX_PATH, szTempPath);
wchar_t wTempName[MAX_PATH + 1]{};
// Get temp directory GetTempFileName(szTempPath, // directory for temp files
if (!GetTempPathW(MAX_PATH, wTempPath)) c_pszPrefix ? c_pszPrefix : "etb", // temp file name prefix
return ""; c_pszPrefix ? true : false, // create unique name
szTempName); // buffer for name
// Prefix must be wide return (szTempName);
wchar_t wPrefix[4] = L"etb";
if (c_pszPrefix && *c_pszPrefix)
{
std::wstring wp = Utf8ToWide(c_pszPrefix);
wcsncpy_s(wPrefix, wp.c_str(), 3);
}
// Create temp file name
if (!GetTempFileNameW(
wTempPath,
wPrefix,
0, // unique number generated by system
wTempName))
return "";
// Convert result to UTF-8 for engine
s_utf8TempName = WideToUtf8(wTempName);
return s_utf8TempName.c_str();
} }
void GetFilePathNameExtension(const char * c_szFile, int len, std::string * pstPath, std::string * pstName, std::string * pstExt) void GetFilePathNameExtension(const char * c_szFile, int len, std::string * pstPath, std::string * pstName, std::string * pstExt)
@@ -60,10 +41,10 @@ void GetFilePathNameExtension(const char * c_szFile, int len, std::string * pstP
if (ext == len && c == '.') if (ext == len && c == '.')
{ {
ext = pos; ext = pos;
break; break;
} }
if (c == '/' || c == '\\') if (c == '/' || c == '\\')
break; break;
} }
@@ -102,7 +83,7 @@ void GetFileExtension(const char* c_szFile, int len, std::string* pstExt)
char c=c_szFile[pos]; char c=c_szFile[pos];
if (ext==len && c=='.') if (ext==len && c=='.')
{ {
ext=pos; ext=pos;
break; break;
} }
@@ -110,7 +91,7 @@ void GetFileExtension(const char* c_szFile, int len, std::string* pstExt)
else if (c=='\\') break; else if (c=='\\') break;
} }
++ext; ++ext;
if (len>ext) if (len>ext)
pstExt->append(c_szFile+ext, len-ext); pstExt->append(c_szFile+ext, len-ext);
} }
@@ -129,7 +110,7 @@ void GetFileNameParts(const char* c_szFile, int len, char* pszPath, char* pszNam
char c=c_szFile[pos]; char c=c_szFile[pos];
if (ext==len && c=='.') if (ext==len && c=='.')
{ {
ext=pos; ext=pos;
break; break;
} }
@@ -146,7 +127,7 @@ void GetFileNameParts(const char* c_szFile, int len, char* pszPath, char* pszNam
else if (c=='\\') break; else if (c=='\\') break;
} }
if (pos) if (pos)
{ {
++pos; ++pos;
for (int i = 0; i < pos; ++i) for (int i = 0; i < pos; ++i)
@@ -166,7 +147,7 @@ void GetFileNameParts(const char* c_szFile, int len, char* pszPath, char* pszNam
pszName[count] = '\0'; pszName[count] = '\0';
} }
++ext; ++ext;
if (len > ext) if (len > ext)
{ {
int count = 0; int count = 0;
@@ -182,10 +163,10 @@ void GetOldIndexingName(char * szName, int Index)
{ {
int dec, sign; int dec, sign;
char Temp[512]; char Temp[512];
strcpy(Temp, _ecvt(Index, 256, &dec, &sign)); strcpy(Temp, _ecvt(Index, 256, &dec, &sign));
Temp[dec] = '\0'; Temp[dec] = '\0';
strcat(szName, Temp); strcat(szName, Temp);
} }
@@ -442,40 +423,38 @@ bool IsGlobalFileName(const char * c_szFileName)
return strchr(c_szFileName, ':') != NULL; return strchr(c_szFileName, ':') != NULL;
} }
void MyCreateDirectory(const char* pathUtf8) void MyCreateDirectory(const char* path)
{ {
if (!pathUtf8 || !*pathUtf8) if (!path || !*path)
return; return;
// Skip drive letter (C:\) char * dir;
const char* path = pathUtf8; const char * p;
if (strlen(path) >= 3 && path[1] == ':')
path += 3;
size_t len = strlen(pathUtf8) + 1; if (strlen(path) >= 3)
char* dirUtf8 = new char[len]; {
if (*(path + 1) == ':') // C:, D: 같은 경우를 체크
path += 3;
}
const char* p = path; p = path;
int len = strlen(path) + 1;
dir = new char[len];
while (*p) while (*p)
{ {
if (*p == '/' || *p == '\\') if (*p == '/' || *p == '\\')
{ {
memset(dirUtf8, 0, len); memset(dir, 0, len);
strncpy(dirUtf8, pathUtf8, p - path + (path - pathUtf8)); strncpy(dir, path, p - path);
CreateDirectory(dir, NULL);
// UTF-8 → UTF-16 for WinAPI
std::wstring wDir = Utf8ToWide(dirUtf8);
CreateDirectoryW(wDir.c_str(), nullptr);
} }
++p; ++p;
} }
// Create final directory too delete [] dir;
std::wstring wFinal = Utf8ToWide(pathUtf8);
CreateDirectoryW(wFinal.c_str(), nullptr);
delete[] dirUtf8;
} }
class CDirRemover : public CDir class CDirRemover : public CDir
@@ -505,31 +484,22 @@ class CDirRemover : public CDir
ms_strDirectoryDeque.push_back(strWorkingFolder); ms_strDirectoryDeque.push_back(strWorkingFolder);
return true; return true;
} }
bool OnFile(const char* c_szPathName, const char* c_szFileName) bool OnFile(const char* c_szPathName, const char* c_szFileName)
{ {
std::string strFullPathName; std::string strFullPathName;
strFullPathName = c_szPathName; strFullPathName = c_szPathName;
strFullPathName += c_szFileName; strFullPathName += c_szFileName;
_chmod(strFullPathName.c_str(), _S_IWRITE);
std::wstring wFullPath = Utf8ToWide(strFullPathName); DeleteFile(strFullPathName.c_str());
// Make writable (use wide version)
_wchmod(wFullPath.c_str(), _S_IWRITE);
// Delete (use wide WinAPI)
DeleteFileW(wFullPath.c_str());
return true; return true;
} }
static void RemoveAllDirectory() static void RemoveAllDirectory()
{ {
for (std::deque<std::string>::iterator itor = ms_strDirectoryDeque.begin(); for (std::deque<std::string>::iterator itor = ms_strDirectoryDeque.begin(); itor != ms_strDirectoryDeque.end(); ++itor)
itor != ms_strDirectoryDeque.end(); ++itor)
{ {
const std::string& dirUtf8 = *itor; const std::string & c_rstrDirectory = *itor;
std::wstring wDir = Utf8ToWide(dirUtf8); RemoveDirectory(c_rstrDirectory.c_str());
RemoveDirectoryW(wDir.c_str());
} }
ms_strDirectoryDeque.clear(); ms_strDirectoryDeque.clear();
@@ -541,19 +511,14 @@ class CDirRemover : public CDir
std::deque<std::string> CDirRemover::ms_strDirectoryDeque; std::deque<std::string> CDirRemover::ms_strDirectoryDeque;
void RemoveAllDirectory(const char* c_szDirectoryName) void RemoveAllDirectory(const char * c_szDirectoryName)
{ {
{ {
CDirRemover remover; CDirRemover remover;
remover.Create("*.*", c_szDirectoryName); remover.Create("*.*", c_szDirectoryName);
CDirRemover::RemoveAllDirectory(); CDirRemover::RemoveAllDirectory();
} }
RemoveDirectory(c_szDirectoryName);
if (c_szDirectoryName && *c_szDirectoryName)
{
std::wstring wDir = Utf8ToWide(c_szDirectoryName);
RemoveDirectoryW(wDir.c_str());
}
} }
void StringExceptCharacter(std::string * pstrString, const char * c_szCharacter) void StringExceptCharacter(std::string * pstrString, const char * c_szCharacter)
@@ -608,15 +573,14 @@ bool SplitLine(const char * c_szLine, const char * c_szDelimeter, std::vector<st
return true; return true;
} }
void GetExcutedFileName(std::string& r_str) void GetExcutedFileName(std::string & r_str)
{ {
wchar_t wPath[MAX_PATH + 1]{}; char szPath[MAX_PATH+1];
GetModuleFileNameW(nullptr, wPath, MAX_PATH); GetModuleFileName(NULL, szPath, MAX_PATH);
wPath[MAX_PATH] = L'\0'; szPath[MAX_PATH] = '\0';
// Convert UTF-16 → UTF-8 for engine use r_str = szPath;
r_str = WideToUtf8(wPath);
} }
const char * _getf(const char* c_szFormat, ...) const char * _getf(const char* c_szFormat, ...)

View File

@@ -27,6 +27,12 @@
#define AssertLog(str) TraceError(str); assert(!str) #define AssertLog(str) TraceError(str); assert(!str)
#ifndef MAKEFOURCC
#define MAKEFOURCC(ch0, ch1, ch2, ch3) \
((DWORD)(BYTE) (ch0 ) | ((DWORD)(BYTE) (ch1) << 8) | \
((DWORD)(BYTE) (ch2) << 16) | ((DWORD)(BYTE) (ch3) << 24))
#endif // defined(MAKEFOURCC)
#ifndef IS_SET #ifndef IS_SET
#define IS_SET(flag,bit) ((flag) & (bit)) #define IS_SET(flag,bit) ((flag) & (bit))
#endif #endif
@@ -209,18 +215,4 @@ void StringExceptCharacter(std::string * pstrString, const char * c_szCharacter)
extern void GetExcutedFileName(std::string & r_str); extern void GetExcutedFileName(std::string & r_str);
template<typename T>
constexpr T LinearInterpolation(const T& tMin, const T& tMax, float fRatio)
{
return T(tMin * (1.0f - fRatio) + tMax * fRatio);
}
template<typename T>
constexpr T HermiteInterpolation(const T& tMin, const T& tMax, float fRatio)
{
fRatio = MINMAX(0.0f, fRatio, 1.0f);
fRatio = fRatio * fRatio * (3.0f - 2.0f * fRatio);
return LinearInterpolation(tMin, tMax, fRatio);
}
#endif #endif

View File

@@ -4,7 +4,6 @@
#include <time.h> #include <time.h>
#include <winsock.h> #include <winsock.h>
#include <imagehlp.h> #include <imagehlp.h>
#include <utf8.h>
FILE* fException; FILE* fException;
@@ -45,21 +44,18 @@ LONG __stdcall EterExceptionFilter(_EXCEPTION_POINTERS* pExceptionInfo)
HANDLE hProcess = GetCurrentProcess(); HANDLE hProcess = GetCurrentProcess();
HANDLE hThread = GetCurrentThread(); HANDLE hThread = GetCurrentThread();
fException = fopen("log/ErrorLog.txt", "wt"); fException = fopen("ErrorLog.txt", "wt");
if (fException) if (fException)
{ {
wchar_t wModuleName[MAX_PATH]{}; char module_name[256];
time_t module_time; time_t module_time;
HMODULE hModule = GetModuleHandleW(nullptr); HMODULE hModule = GetModuleHandle(NULL);
GetModuleFileNameW(hModule, wModuleName, MAX_PATH); GetModuleFileName(hModule, module_name, sizeof(module_name));
module_time = (time_t)GetTimestampForLoadedLibrary(hModule); module_time = (time_t)GetTimestampForLoadedLibrary(hModule);
// Convert once for logging fprintf(fException, "Module Name: %s\n", module_name);
std::string moduleNameUtf8 = WideToUtf8(wModuleName);
fprintf(fException, "Module Name: %s\n", moduleNameUtf8.c_str());
fprintf(fException, "Time Stamp: 0x%08x - %s\n", (unsigned int)module_time, ctime(&module_time)); fprintf(fException, "Time Stamp: 0x%08x - %s\n", (unsigned int)module_time, ctime(&module_time));
fprintf(fException, "\n"); fprintf(fException, "\n");
fprintf(fException, "Exception Type: 0x%08x\n", pExceptionInfo->ExceptionRecord->ExceptionCode); fprintf(fException, "Exception Type: 0x%08x\n", pExceptionInfo->ExceptionRecord->ExceptionCode);

View File

@@ -216,14 +216,22 @@ public:
public: public:
DecryptBuffer(unsigned size) DecryptBuffer(unsigned size)
{ {
static unsigned count = 0;
static unsigned sum = 0;
static unsigned maxSize = 0;
sum += size;
count++;
maxSize = std::max(size, maxSize);
if (size >= LOCAL_BUF_SIZE) if (size >= LOCAL_BUF_SIZE)
{ {
m_buf = new char[size]; m_buf = new char[size];
dbg_printf("DecryptBuffer - AllocHeap %d\n", size); dbg_printf("DecryptBuffer - AllocHeap %d max(%d) ave(%d)\n", size, maxSize/1024, sum/count);
} }
else else
{ {
dbg_printf("DecryptBuffer - AllocStack %d\n", size); dbg_printf("DecryptBuffer - AllocStack %d max(%d) ave(%d)\n", size, maxSize/1024, sum/count);
m_buf = m_local_buf; m_buf = m_local_buf;
} }
} }
@@ -231,12 +239,12 @@ public:
{ {
if (m_local_buf != m_buf) if (m_local_buf != m_buf)
{ {
dbg_printf("DecryptBuffer - FreeHeap\n"); dbg_printf("DecruptBuffer - FreeHeap\n");
delete [] m_buf; delete [] m_buf;
} }
else else
{ {
dbg_printf("DecryptBuffer - FreeStack\n"); dbg_printf("DecruptBuffer - FreeStack\n");
} }
} }
void* GetBufferPtr() void* GetBufferPtr()

View File

@@ -3,8 +3,7 @@
add_library(EterGrnLib STATIC ${FILE_SOURCES}) add_library(EterGrnLib STATIC ${FILE_SOURCES})
target_link_libraries(EterGrnLib target_link_libraries(EterGrnLib
cryptopp-static lzo2
mio
) )
GroupSourcesByFolder(EterGrnLib) GroupSourcesByFolder(EterGrnLib)

View File

@@ -1,153 +0,0 @@
#include "Deform.h"
#include <xmmintrin.h>
#include <emmintrin.h>
void DeformPWNT3432toGrannyPNGBT33332D(granny_int32x Count, void const* SourceInit, void* DestInit,
granny_matrix_4x4 const* Transforms,
granny_int32x CopySize, granny_int32x SourceStride, granny_int32x DestStride)
{
const float inv255 = 1.0f / 255.0f;
const granny_pwnt3432_vertex* src = (const granny_pwnt3432_vertex*)SourceInit;
granny_pnt332_vertex* dst = (granny_pnt332_vertex*)DestInit;
while (Count--) {
const __m128 srcPos = _mm_set_ps(1.0f, src->Position[2], src->Position[1], src->Position[0]);
const __m128 srcNrm = _mm_set_ps(0.0f, src->Normal[2], src->Normal[1], src->Normal[0]);
const __m128 px = _mm_shuffle_ps(srcPos, srcPos, _MM_SHUFFLE(0, 0, 0, 0));
const __m128 py = _mm_shuffle_ps(srcPos, srcPos, _MM_SHUFFLE(1, 1, 1, 1));
const __m128 pz = _mm_shuffle_ps(srcPos, srcPos, _MM_SHUFFLE(2, 2, 2, 2));
const __m128 pw = _mm_shuffle_ps(srcPos, srcPos, _MM_SHUFFLE(3, 3, 3, 3));
const __m128 nx = _mm_shuffle_ps(srcNrm, srcNrm, _MM_SHUFFLE(0, 0, 0, 0));
const __m128 ny = _mm_shuffle_ps(srcNrm, srcNrm, _MM_SHUFFLE(1, 1, 1, 1));
const __m128 nz = _mm_shuffle_ps(srcNrm, srcNrm, _MM_SHUFFLE(2, 2, 2, 2));
__m128 P = _mm_setzero_ps();
__m128 N = _mm_setzero_ps();
for (int i = 0; i < 4; ++i) {
const int bi = src->BoneIndices[i];
const float wS = (float)src->BoneWeights[i] * inv255;
if (wS <= 0.0f) continue;
const float* m = (const float*)(&Transforms[bi]);
const __m128 r0 = _mm_loadu_ps(m + 0);
const __m128 r1 = _mm_loadu_ps(m + 4);
const __m128 r2 = _mm_loadu_ps(m + 8);
const __m128 r3 = _mm_loadu_ps(m + 12);
__m128 p = _mm_add_ps(_mm_mul_ps(r0, px), _mm_mul_ps(r1, py));
p = _mm_add_ps(p, _mm_mul_ps(r2, pz));
p = _mm_add_ps(p, _mm_mul_ps(r3, pw));
const __m128 w = _mm_set1_ps(wS);
P = _mm_add_ps(P, _mm_mul_ps(p, w));
__m128 n = _mm_add_ps(_mm_mul_ps(r0, nx), _mm_mul_ps(r1, ny));
n = _mm_add_ps(n, _mm_mul_ps(r2, nz));
N = _mm_add_ps(N, _mm_mul_ps(n, w));
}
float pOut[4], nOut[4];
_mm_storeu_ps(pOut, P);
_mm_storeu_ps(nOut, N);
dst->Position[0] = pOut[0];
dst->Position[1] = pOut[1];
dst->Position[2] = pOut[2];
dst->Normal[0] = nOut[0];
dst->Normal[1] = nOut[1];
dst->Normal[2] = nOut[2];
dst->UV[0] = src->UV[0];
dst->UV[1] = src->UV[1];
src = (const granny_pwnt3432_vertex*)((const granny_uint8*)src + SourceStride);
dst = (granny_pnt332_vertex*)((granny_uint8*)dst + DestStride);
}
}
void DeformPWNT3432toGrannyPNGBT33332I(granny_int32x Count, void const* SourceInit, void* DestInit,
granny_int32x const* TransformTable, granny_matrix_4x4 const* Transforms,
granny_int32x CopySize, granny_int32x SourceStride, granny_int32x DestStride)
{
const float inv255 = 1.0f / 255.0f;
const granny_pwnt3432_vertex* src = (const granny_pwnt3432_vertex*)SourceInit;
granny_pnt332_vertex* dst = (granny_pnt332_vertex*)DestInit;
while (Count--) {
const __m128 srcPos = _mm_set_ps(1.0f, src->Position[2], src->Position[1], src->Position[0]);
const __m128 srcNrm = _mm_set_ps(0.0f, src->Normal[2], src->Normal[1], src->Normal[0]);
const __m128 px = _mm_shuffle_ps(srcPos, srcPos, _MM_SHUFFLE(0, 0, 0, 0));
const __m128 py = _mm_shuffle_ps(srcPos, srcPos, _MM_SHUFFLE(1, 1, 1, 1));
const __m128 pz = _mm_shuffle_ps(srcPos, srcPos, _MM_SHUFFLE(2, 2, 2, 2));
const __m128 pw = _mm_shuffle_ps(srcPos, srcPos, _MM_SHUFFLE(3, 3, 3, 3));
const __m128 nx = _mm_shuffle_ps(srcNrm, srcNrm, _MM_SHUFFLE(0, 0, 0, 0));
const __m128 ny = _mm_shuffle_ps(srcNrm, srcNrm, _MM_SHUFFLE(1, 1, 1, 1));
const __m128 nz = _mm_shuffle_ps(srcNrm, srcNrm, _MM_SHUFFLE(2, 2, 2, 2));
__m128 P = _mm_setzero_ps();
__m128 N = _mm_setzero_ps();
for (int i = 0; i < 4; ++i) {
const int bi = TransformTable[src->BoneIndices[i]];
const float wS = (float)src->BoneWeights[i] * inv255;
if (wS <= 0.0f) continue;
const float* m = (const float*)(&Transforms[bi]);
const __m128 r0 = _mm_loadu_ps(m + 0);
const __m128 r1 = _mm_loadu_ps(m + 4);
const __m128 r2 = _mm_loadu_ps(m + 8);
const __m128 r3 = _mm_loadu_ps(m + 12);
__m128 p = _mm_add_ps(_mm_mul_ps(r0, px), _mm_mul_ps(r1, py));
p = _mm_add_ps(p, _mm_mul_ps(r2, pz));
p = _mm_add_ps(p, _mm_mul_ps(r3, pw));
const __m128 w = _mm_set1_ps(wS);
P = _mm_add_ps(P, _mm_mul_ps(p, w));
__m128 n = _mm_add_ps(_mm_mul_ps(r0, nx), _mm_mul_ps(r1, ny));
n = _mm_add_ps(n, _mm_mul_ps(r2, nz));
N = _mm_add_ps(N, _mm_mul_ps(n, w));
}
float pOut[4], nOut[4];
_mm_storeu_ps(pOut, P);
_mm_storeu_ps(nOut, N);
dst->Position[0] = pOut[0];
dst->Position[1] = pOut[1];
dst->Position[2] = pOut[2];
dst->Normal[0] = nOut[0];
dst->Normal[1] = nOut[1];
dst->Normal[2] = nOut[2];
dst->UV[0] = src->UV[0];
dst->UV[1] = src->UV[1];
src = (const granny_pwnt3432_vertex*)((const granny_uint8*)src + SourceStride);
dst = (granny_pnt332_vertex*)((granny_uint8*)dst + DestStride);
}
}
void DeformPWNT3432toGrannyPNGBT33332(granny_int32x Count, void const* SourceInit, void* DestInit,
granny_int32x const* TransformTable, granny_matrix_4x4 const* Transforms,
granny_int32x CopySize, granny_int32x SourceStride, granny_int32x DestStride)
{
if (TransformTable) {
DeformPWNT3432toGrannyPNGBT33332I(Count, SourceInit, DestInit, TransformTable, Transforms, CopySize, SourceStride, DestStride);
}
else {
DeformPWNT3432toGrannyPNGBT33332D(Count, SourceInit, DestInit, Transforms, CopySize, SourceStride, DestStride);
}
}

View File

@@ -1,6 +0,0 @@
#pragma once
#include <granny.h>
void DeformPWNT3432toGrannyPNGBT33332(granny_int32x Count, void const* SourceInit, void* DestInit,
granny_int32x const* TransformTable, granny_matrix_4x4 const* Transforms,
granny_int32x CopySize, granny_int32x SourceStride, granny_int32x DestStride);

View File

@@ -58,10 +58,10 @@ static CGraphicVertexBuffer* __AllocDeformVertexBuffer(unsigned deformableVertex
CGraphicVertexBuffer* pkNewVB = new CGraphicVertexBuffer; CGraphicVertexBuffer* pkNewVB = new CGraphicVertexBuffer;
if (!pkNewVB->Create( if (!pkNewVB->Create(
capacity, capacity,
D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1, D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1,
D3DUSAGE_DYNAMIC, D3DUSAGE_WRITEONLY,
D3DPOOL_DEFAULT)) D3DPOOL_MANAGED))
{ {
TraceError("NEW_ERROR %8d: %d(%d)", time(NULL) - base, capacity, deformableVertexCount); TraceError("NEW_ERROR %8d: %d(%d)", time(NULL) - base, capacity, deformableVertexCount);
} }
@@ -101,10 +101,10 @@ void __ReserveSharedVertexBuffers(unsigned index, unsigned count)
{ {
CGraphicVertexBuffer* pkNewVB = new CGraphicVertexBuffer; CGraphicVertexBuffer* pkNewVB = new CGraphicVertexBuffer;
pkNewVB->Create( pkNewVB->Create(
capacity, capacity,
D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1, D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1,
D3DUSAGE_DYNAMIC, D3DUSAGE_WRITEONLY,
D3DPOOL_DEFAULT); D3DPOOL_MANAGED);
gs_vbs[index].push_back(pkNewVB); gs_vbs[index].push_back(pkNewVB);
} }
NANOEND NANOEND

View File

@@ -4,9 +4,9 @@
#include <windows.h> #include <windows.h>
#include <d3d9.h> #include <d3d9.h>
#include "Eterlib/ReferenceObject.h" #include "../eterlib/ReferenceObject.h"
#include "Eterlib/Ref.h" #include "../eterlib/Ref.h"
#include "Eterlib/GrpImageInstance.h" #include "../eterlib/GrpImageInstance.h"
#include "Util.h" #include "Util.h"
class CGrannyMaterial : public CReferenceObject class CGrannyMaterial : public CReferenceObject

View File

@@ -2,7 +2,6 @@
#include "Mesh.h" #include "Mesh.h"
#include "Model.h" #include "Model.h"
#include "Material.h" #include "Material.h"
#include "Deform.h"
granny_data_type_definition GrannyPNT3322VertexType[5] = granny_data_type_definition GrannyPNT3322VertexType[5] =
{ {
@@ -43,45 +42,30 @@ void CGrannyMesh::NEW_LoadVertices(void * dstBaseVertices)
GrannyCopyMeshVertices(pgrnMesh, m_pgrnMeshType, dstVertices); GrannyCopyMeshVertices(pgrnMesh, m_pgrnMeshType, dstVertices);
} }
void CGrannyMesh::DeformPNTVertices(void* dstBaseVertices, D3DXMATRIX* boneMatrices, granny_mesh_binding* pgrnMeshBinding) const void CGrannyMesh::DeformPNTVertices(void * dstBaseVertices, D3DXMATRIX * boneMatrices, granny_mesh_binding* pgrnMeshBinding) const
{ {
assert(dstBaseVertices != NULL); assert(dstBaseVertices != NULL);
assert(boneMatrices != NULL); assert(boneMatrices != NULL);
assert(m_pgrnMeshDeformer != NULL); assert(m_pgrnMeshDeformer != NULL);
const granny_mesh* pgrnMesh = GetGrannyMeshPointer(); const granny_mesh * pgrnMesh = GetGrannyMeshPointer();
TPNTVertex* srcVertices = (TPNTVertex*)GrannyGetMeshVertices(pgrnMesh);
TPNTVertex* dstVertices = ((TPNTVertex*)dstBaseVertices) + m_vtxBasePos;
TPNTVertex * srcVertices = (TPNTVertex *) GrannyGetMeshVertices(pgrnMesh);
TPNTVertex * dstVertices = ((TPNTVertex *) dstBaseVertices) + m_vtxBasePos;
int vtxCount = GrannyGetMeshVertexCount(pgrnMesh); int vtxCount = GrannyGetMeshVertexCount(pgrnMesh);
// WORK // WORK
granny_int32x* boneIndices = (granny_int32x*)GrannyGetMeshBindingToBoneIndices(pgrnMeshBinding); granny_int32x * boneIndices = (granny_int32x*)GrannyGetMeshBindingToBoneIndices(pgrnMeshBinding);
// END_OF_WORK // END_OF_WORK
extern bool CPU_HAS_SSE2; GrannyDeformVertices(
if (CPU_HAS_SSE2) { m_pgrnMeshDeformer,
DeformPWNT3432toGrannyPNGBT33332( boneIndices,
vtxCount, (float *)boneMatrices,
srcVertices, vtxCount,
dstVertices, srcVertices,
boneIndices, dstVertices);
(granny_matrix_4x4 const*)boneMatrices,
sizeof(granny_pwnt3432_vertex),
sizeof(granny_pwnt3432_vertex),
sizeof(granny_pnt332_vertex)
);
}
else {
GrannyDeformVertices(
m_pgrnMeshDeformer,
boneIndices,
(float*)boneMatrices,
vtxCount,
srcVertices,
dstVertices);
}
} }
bool CGrannyMesh::CanDeformPNTVertices() const bool CGrannyMesh::CanDeformPNTVertices() const

View File

@@ -109,7 +109,7 @@ bool CGrannyModel::LoadPNTVertices()
assert(m_meshs != NULL); assert(m_meshs != NULL);
if (!m_pntVtxBuf.Create(m_rigidVtxCount, m_dwFvF, D3DUSAGE_WRITEONLY, D3DPOOL_DEFAULT)) if (!m_pntVtxBuf.Create(m_rigidVtxCount, m_dwFvF, D3DUSAGE_WRITEONLY, D3DPOOL_MANAGED))
return false; return false;
void* vertices; void* vertices;
@@ -257,7 +257,7 @@ BOOL CGrannyModel::CheckMeshIndex(int iIndex) const
{ {
if (iIndex < 0) if (iIndex < 0)
return FALSE; return FALSE;
if (iIndex >= GetMeshCount()) if (iIndex >= m_meshNodeSize)
return FALSE; return FALSE;
return TRUE; return TRUE;
@@ -361,7 +361,7 @@ bool CGrannyModel::__LoadVertices()
// assert((m_dwFvF & (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1)) == m_dwFvF); // assert((m_dwFvF & (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1)) == m_dwFvF);
// if (!m_pntVtxBuf.Create(m_rigidVtxCount, D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1, D3DUSAGE_WRITEONLY, D3DPOOL_MANAGED)) // if (!m_pntVtxBuf.Create(m_rigidVtxCount, D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1, D3DUSAGE_WRITEONLY, D3DPOOL_MANAGED))
if (!m_pntVtxBuf.Create(m_rigidVtxCount, m_dwFvF, D3DUSAGE_WRITEONLY, D3DPOOL_DEFAULT)) if (!m_pntVtxBuf.Create(m_rigidVtxCount, m_dwFvF, D3DUSAGE_WRITEONLY, D3DPOOL_MANAGED))
return false; return false;
void* vertices; void* vertices;

View File

@@ -1,7 +1,7 @@
#pragma once #pragma once
#include "Eterlib/GrpVertexBuffer.h" #include "../eterlib/GrpVertexBuffer.h"
#include "Eterlib/GrpIndexBuffer.h" #include "../eterlib/GrpIndexBuffer.h"
#include "Mesh.h" #include "Mesh.h"

View File

@@ -1,7 +1,7 @@
#include "StdAfx.h" #include "StdAfx.h"
#include "ModelInstance.h" #include "ModelInstance.h"
#include "Model.h" #include "Model.h"
#include "EterLib/ResourceManager.h" #include "../EterLib/ResourceManager.h"
CGrannyModel* CGrannyModelInstance::GetModel() CGrannyModel* CGrannyModelInstance::GetModel()

View File

@@ -1,8 +1,8 @@
#pragma once #pragma once
//#define CACHE_DEFORMED_VERTEX //#define CACHE_DEFORMED_VERTEX
#include "Eterlib/GrpImage.h" #include "../eterlib/GrpImage.h"
#include "Eterlib/GrpCollisionObject.h" #include "../eterlib/GrpCollisionObject.h"
#include "Model.h" #include "Model.h"
#include "Motion.h" #include "Motion.h"

View File

@@ -176,7 +176,7 @@ bool CGrannyModelInstance::Intersect(const D3DXMATRIX * c_pMatrix,
*/ */
} }
#include "EterBase/Timer.h" #include "../EterBase/Timer.h"
void CGrannyModelInstance::GetBoundBox(D3DXVECTOR3* vtMin, D3DXVECTOR3* vtMax) void CGrannyModelInstance::GetBoundBox(D3DXVECTOR3* vtMin, D3DXVECTOR3* vtMax)
{ {

View File

@@ -232,7 +232,9 @@ void CGrannyModelInstance::__CreateDynamicVertexBuffer()
{ {
if (!m_kLocalDeformableVertexBuffer.Create(vtxCount, if (!m_kLocalDeformableVertexBuffer.Create(vtxCount,
D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1, D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1,
D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT //D3DUSAGE_DYNAMIC, D3DPOOL_SYSTEMMEM
D3DUSAGE_WRITEONLY, D3DPOOL_MANAGED
)) ))
return; return;
} }

View File

@@ -1,11 +1,11 @@
#include "StdAfx.h" #include "StdAfx.h"
#include "Eterlib/StateManager.h" #include "../eterlib/StateManager.h"
#include "ModelInstance.h" #include "ModelInstance.h"
#include "Model.h" #include "Model.h"
#ifdef _TEST #ifdef _TEST
#include "Eterlib/GrpScreen.h" #include "../eterlib/GrpScreen.h"
void Granny_RenderBoxBones(const granny_skeleton* pkGrnSkeleton, const granny_world_pose* pkGrnWorldPose, const D3DXMATRIX& matBase) void Granny_RenderBoxBones(const granny_skeleton* pkGrnSkeleton, const granny_world_pose* pkGrnWorldPose, const D3DXMATRIX& matBase)
{ {

View File

@@ -1,5 +1,5 @@
#include "StdAfx.h" #include "StdAfx.h"
#include "Eterbase/Debug.h" #include "../eterbase/Debug.h"
#include "ModelInstance.h" #include "ModelInstance.h"
#include "Model.h" #include "Model.h"

View File

@@ -5,9 +5,9 @@
//#include <crtdbg.h> //#include <crtdbg.h>
#include <granny.h> #include <granny.h>
#include "EterBase/Utils.h" #include "../eterBase/Utils.h"
#include "EterBase/Debug.h" #include "../eterBase/Debug.h"
#include "EterBase/Stl.h" #include "../eterBase/Stl.h"
#include "Util.h" #include "Util.h"

View File

@@ -1,5 +1,5 @@
#include "StdAfx.h" #include "StdAfx.h"
#include "Eterbase/Debug.h" #include "../eterbase/Debug.h"
#include "Thing.h" #include "Thing.h"
#include "ThingInstance.h" #include "ThingInstance.h"

View File

@@ -1,7 +1,7 @@
#include "StdAfx.h" #include "StdAfx.h"
#include "Eterbase/Debug.h" #include "../eterbase/Debug.h"
#include "Eterlib/Camera.h" #include "../eterlib/Camera.h"
#include "EterBase/Timer.h" #include "../eterBase/Timer.h"
#include "ThingInstance.h" #include "ThingInstance.h"
#include "Thing.h" #include "Thing.h"
#include "ModelInstance.h" #include "ModelInstance.h"
@@ -534,7 +534,7 @@ void CGraphicThingInstance::RegisterMotionThing(DWORD dwMotionKey, CGraphicThing
{ {
CGraphicThing::TRef * pMotionRef = new CGraphicThing::TRef; CGraphicThing::TRef * pMotionRef = new CGraphicThing::TRef;
pMotionRef->SetPointer(pMotionThing); pMotionRef->SetPointer(pMotionThing);
m_roMotionThingMap.insert(std::make_pair(dwMotionKey, pMotionRef)); m_roMotionThingMap.insert(std::map<DWORD, CGraphicThing::TRef *>::value_type(dwMotionKey, pMotionRef));
} }
void CGraphicThingInstance::ResetLocalTime() void CGraphicThingInstance::ResetLocalTime()

View File

@@ -1,8 +1,8 @@
#pragma once #pragma once
#include "Eterbase/Stl.h" #include "../eterbase/Stl.h"
#include "Eterlib/GrpObjectInstance.h" #include "../eterlib/GrpObjectInstance.h"
#include "Eterlib/GrpShadowTexture.h" #include "../eterlib/GrpShadowTexture.h"
#include "LODController.h" #include "LODController.h"

View File

@@ -3,8 +3,7 @@
add_library(EterImageLib STATIC ${FILE_SOURCES}) add_library(EterImageLib STATIC ${FILE_SOURCES})
target_link_libraries(EterImageLib target_link_libraries(EterImageLib
cryptopp-static lzo2
mio
) )
GroupSourcesByFolder(EterImageLib) GroupSourcesByFolder(EterImageLib)

File diff suppressed because it is too large Load Diff

View File

@@ -1,145 +0,0 @@
//--------------------------------------------------------------------------------------
// File: DDSTextureLoader9.h
//
// Functions for loading a DDS texture and creating a Direct3D runtime resource for it
//
// Note these functions are useful as a light-weight runtime loader for DDS files. For
// a full-featured DDS file reader, writer, and texture processing pipeline see
// the 'Texconv' sample and the 'DirectXTex' library.
//
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
//
// http://go.microsoft.com/fwlink/?LinkId=248926
//--------------------------------------------------------------------------------------
#pragma once
#ifndef DIRECT3D_VERSION
#define DIRECT3D_VERSION 0x900
#endif
#include <d3d9.h>
#include <cstddef>
#include <cstdint>
namespace DirectX
{
// Standard version
HRESULT CreateDDSTextureFromMemory(
_In_ LPDIRECT3DDEVICE9 d3dDevice,
_In_reads_bytes_(ddsDataSize) const uint8_t* ddsData,
_In_ size_t ddsDataSize,
_Outptr_ LPDIRECT3DBASETEXTURE9* texture,
bool generateMipsIfMissing = false) noexcept;
HRESULT CreateDDSTextureFromFile(
_In_ LPDIRECT3DDEVICE9 d3dDevice,
_In_z_ const wchar_t* fileName,
_Outptr_ LPDIRECT3DBASETEXTURE9* texture,
bool generateMipsIfMissing = false) noexcept;
// Extended version
HRESULT CreateDDSTextureFromMemoryEx(
_In_ LPDIRECT3DDEVICE9 d3dDevice,
_In_reads_bytes_(ddsDataSize) const uint8_t* ddsData,
_In_ size_t ddsDataSize,
_In_ DWORD usage,
_In_ D3DPOOL pool,
bool generateMipsIfMissing,
_Outptr_ LPDIRECT3DBASETEXTURE9* texture) noexcept;
HRESULT CreateDDSTextureFromFileEx(
_In_ LPDIRECT3DDEVICE9 d3dDevice,
_In_z_ const wchar_t* fileName,
_In_ DWORD usage,
_In_ D3DPOOL pool,
bool generateMipsIfMissing,
_Outptr_ LPDIRECT3DBASETEXTURE9* texture) noexcept;
// Type-specific standard versions
HRESULT CreateDDSTextureFromMemory(
_In_ LPDIRECT3DDEVICE9 d3dDevice,
_In_reads_bytes_(ddsDataSize) const uint8_t* ddsData,
_In_ size_t ddsDataSize,
_Outptr_ LPDIRECT3DTEXTURE9* texture,
bool generateMipsIfMissing = false) noexcept;
HRESULT CreateDDSTextureFromFile(
_In_ LPDIRECT3DDEVICE9 d3dDevice,
_In_z_ const wchar_t* fileName,
_Outptr_ LPDIRECT3DTEXTURE9* texture,
bool generateMipsIfMissing = false) noexcept;
HRESULT CreateDDSTextureFromMemory(
_In_ LPDIRECT3DDEVICE9 d3dDevice,
_In_reads_bytes_(ddsDataSize) const uint8_t* ddsData,
_In_ size_t ddsDataSize,
_Outptr_ LPDIRECT3DCUBETEXTURE9* texture) noexcept;
HRESULT CreateDDSTextureFromFile(
_In_ LPDIRECT3DDEVICE9 d3dDevice,
_In_z_ const wchar_t* fileName,
_Outptr_ LPDIRECT3DCUBETEXTURE9* texture) noexcept;
HRESULT CreateDDSTextureFromMemory(
_In_ LPDIRECT3DDEVICE9 d3dDevice,
_In_reads_bytes_(ddsDataSize) const uint8_t* ddsData,
_In_ size_t ddsDataSize,
_Outptr_ LPDIRECT3DVOLUMETEXTURE9* texture) noexcept;
HRESULT CreateDDSTextureFromFile(
_In_ LPDIRECT3DDEVICE9 d3dDevice,
_In_z_ const wchar_t* fileName,
_Outptr_ LPDIRECT3DVOLUMETEXTURE9* texture) noexcept;
// Type-specific extended versions
HRESULT CreateDDSTextureFromMemoryEx(
_In_ LPDIRECT3DDEVICE9 d3dDevice,
_In_reads_bytes_(ddsDataSize) const uint8_t* ddsData,
_In_ size_t ddsDataSize,
_In_ DWORD usage,
_In_ D3DPOOL pool,
bool generateMipsIfMissing,
_Outptr_ LPDIRECT3DTEXTURE9* texture) noexcept;
HRESULT CreateDDSTextureFromFileEx(
_In_ LPDIRECT3DDEVICE9 d3dDevice,
_In_z_ const wchar_t* fileName,
_In_ DWORD usage,
_In_ D3DPOOL pool,
bool generateMipsIfMissing,
_Outptr_ LPDIRECT3DTEXTURE9* texture) noexcept;
HRESULT CreateDDSTextureFromMemoryEx(
_In_ LPDIRECT3DDEVICE9 d3dDevice,
_In_reads_bytes_(ddsDataSize) const uint8_t* ddsData,
_In_ size_t ddsDataSize,
_In_ DWORD usage,
_In_ D3DPOOL pool,
_Outptr_ LPDIRECT3DCUBETEXTURE9* texture) noexcept;
HRESULT CreateDDSTextureFromFileEx(
_In_ LPDIRECT3DDEVICE9 d3dDevice,
_In_z_ const wchar_t* fileName,
_In_ DWORD usage,
_In_ D3DPOOL pool,
_Outptr_ LPDIRECT3DCUBETEXTURE9* texture) noexcept;
HRESULT CreateDDSTextureFromMemoryEx(
_In_ LPDIRECT3DDEVICE9 d3dDevice,
_In_reads_bytes_(ddsDataSize) const uint8_t* ddsData,
_In_ size_t ddsDataSize,
_In_ DWORD usage,
_In_ D3DPOOL pool,
_Outptr_ LPDIRECT3DVOLUMETEXTURE9* texture) noexcept;
HRESULT CreateDDSTextureFromFileEx(
_In_ LPDIRECT3DDEVICE9 d3dDevice,
_In_z_ const wchar_t* fileName,
_In_ DWORD usage,
_In_ D3DPOOL pool,
_Outptr_ LPDIRECT3DVOLUMETEXTURE9* texture) noexcept;
}

Some files were not shown because too many files have changed in this diff Show More