forked from metin-server/m2dev-client-src
Compare commits
2 Commits
revert-64-
...
particle-b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
35c183bd66 | ||
|
|
5db6e9c3d9 |
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -0,0 +1 @@
|
||||
*.lib filter=lfs diff=lfs merge=lfs -text
|
||||
|
||||
35
.github/workflows/main.yml
vendored
35
.github/workflows/main.yml
vendored
@@ -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
64
.gitignore
vendored
@@ -1,63 +1 @@
|
||||
/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
|
||||
build
|
||||
|
||||
@@ -2,12 +2,9 @@
|
||||
|
||||
project(m2dev-client-src)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
# ASan support
|
||||
option(ENABLE_ASAN "Enable AddressSanitizer" OFF)
|
||||
|
||||
set(CMAKE_MODULE_PATH
|
||||
${CMAKE_MODULE_PATH}
|
||||
"${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(/MP)
|
||||
|
||||
if(MSVC)
|
||||
add_compile_definitions(UNICODE _UNICODE)
|
||||
endif()
|
||||
|
||||
add_compile_options(
|
||||
$<$<CXX_COMPILER_ID:MSVC>:/wd4828>
|
||||
$<$<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(-DWIN32_LEAN_AND_MEAN)
|
||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||
|
||||
17
README.md
17
README.md
@@ -1,16 +1 @@
|
||||
# Client Source Repository
|
||||
|
||||
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
|
||||
* **PK Mode:** Resolved conflict for Hostile mode when both players have negative alignment, added PK_PROTECT mode safeguards.
|
||||
# m2dev-client-src
|
||||
8421
extern/include/MSS.H
vendored
Normal file
8421
extern/include/MSS.H
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2589
extern/include/argparse.hpp
vendored
2589
extern/include/argparse.hpp
vendored
File diff suppressed because it is too large
Load Diff
2
extern/include/miniaudio.c
vendored
2
extern/include/miniaudio.c
vendored
@@ -1,2 +0,0 @@
|
||||
#define MINIAUDIO_IMPLEMENTATION
|
||||
#include "miniaudio.h"
|
||||
93468
extern/include/miniaudio.h
vendored
93468
extern/include/miniaudio.h
vendored
File diff suppressed because it is too large
Load Diff
666
extern/include/pcg_extras.hpp
vendored
666
extern/include/pcg_extras.hpp
vendored
@@ -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
|
||||
1951
extern/include/pcg_random.hpp
vendored
1951
extern/include/pcg_random.hpp
vendored
File diff suppressed because it is too large
Load Diff
1006
extern/include/pcg_uint128.hpp
vendored
1006
extern/include/pcg_uint128.hpp
vendored
File diff suppressed because it is too large
Load Diff
840
extern/include/utf8.h
vendored
840
extern/include/utf8.h
vendored
@@ -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;
|
||||
}
|
||||
1
extern/library/CMakeLists.txt
vendored
1
extern/library/CMakeLists.txt
vendored
@@ -1,5 +1,6 @@
|
||||
add_subdirectory(DirectX)
|
||||
add_subdirectory(Granny)
|
||||
add_subdirectory(MilesSoundSystem)
|
||||
add_subdirectory(Python)
|
||||
add_subdirectory(SpeedTree)
|
||||
add_subdirectory(WebView)
|
||||
BIN
extern/library/DirectX/d3d9.lib
vendored
BIN
extern/library/DirectX/d3d9.lib
vendored
Binary file not shown.
BIN
extern/library/DirectX/d3dx9.lib
vendored
BIN
extern/library/DirectX/d3dx9.lib
vendored
Binary file not shown.
BIN
extern/library/DirectX/dinput8.lib
vendored
BIN
extern/library/DirectX/dinput8.lib
vendored
Binary file not shown.
BIN
extern/library/DirectX/dxguid.lib
vendored
BIN
extern/library/DirectX/dxguid.lib
vendored
Binary file not shown.
BIN
extern/library/Granny/granny2_static.lib
vendored
BIN
extern/library/Granny/granny2_static.lib
vendored
Binary file not shown.
6
extern/library/MilesSoundSystem/CMakeLists.txt
vendored
Normal file
6
extern/library/MilesSoundSystem/CMakeLists.txt
vendored
Normal 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"
|
||||
)
|
||||
3
extern/library/MilesSoundSystem/mss64.lib
vendored
Normal file
3
extern/library/MilesSoundSystem/mss64.lib
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:ea999a3c3f5e22bea81b4f2658dfbe074fa1c63d3073de789735fc383cbe0f05
|
||||
size 3145894
|
||||
BIN
extern/library/Python/python27_static.lib
vendored
BIN
extern/library/Python/python27_static.lib
vendored
Binary file not shown.
BIN
extern/library/SpeedTree/speedtree_static.lib
vendored
BIN
extern/library/SpeedTree/speedtree_static.lib
vendored
Binary file not shown.
BIN
extern/library/SpeedTree/speedtree_staticd.lib
vendored
BIN
extern/library/SpeedTree/speedtree_staticd.lib
vendored
Binary file not shown.
BIN
extern/library/WebView/WebView2LoaderStatic.lib
vendored
BIN
extern/library/WebView/WebView2LoaderStatic.lib
vendored
Binary file not shown.
@@ -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)
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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{};
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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{};
|
||||
};
|
||||
@@ -1,9 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
//#include <windows.h>
|
||||
|
||||
#include "EterBase/CRC32.h"
|
||||
#include "EterBase/Utils.h"
|
||||
#include "EterBase/Debug.h"
|
||||
|
||||
#include <algorithm>
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
};
|
||||
@@ -1,4 +1,3 @@
|
||||
add_subdirectory(AudioLib)
|
||||
add_subdirectory(Discord)
|
||||
add_subdirectory(EffectLib)
|
||||
add_subdirectory(EterBase)
|
||||
@@ -6,12 +5,12 @@ add_subdirectory(EterGrnLib)
|
||||
add_subdirectory(EterImageLib)
|
||||
add_subdirectory(EterLib)
|
||||
add_subdirectory(EterLocale)
|
||||
add_subdirectory(EterPack)
|
||||
add_subdirectory(EterPythonLib)
|
||||
add_subdirectory(GameLib)
|
||||
add_subdirectory(MilesLib)
|
||||
add_subdirectory(PRTerrainLib)
|
||||
add_subdirectory(ScriptLib)
|
||||
add_subdirectory(SpeedTreeLib)
|
||||
add_subdirectory(SphereLib)
|
||||
add_subdirectory(UserInterface)
|
||||
add_subdirectory(PackMaker)
|
||||
add_subdirectory(PackLib)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "connection.h"
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define NOMCX
|
||||
#define NOSERVICE
|
||||
#define NOIME
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "discord_rpc.h"
|
||||
#include "discord_register.h"
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define NOMCX
|
||||
#define NOSERVICE
|
||||
#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)
|
||||
{
|
||||
wchar_t appId[32];
|
||||
int app = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, applicationId, -1, appId, 32);
|
||||
if (app <= 0)
|
||||
return;
|
||||
MultiByteToWideChar(CP_UTF8, 0, applicationId, -1, appId, 32);
|
||||
|
||||
wchar_t openCommand[1024];
|
||||
const wchar_t* wcommand = nullptr;
|
||||
if (command && command[0]) {
|
||||
const auto commandBufferLen = sizeof(openCommand) / sizeof(*openCommand);
|
||||
|
||||
int ok = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, command, -1, openCommand, commandBufferLen);
|
||||
if (ok <= 0)
|
||||
return;
|
||||
|
||||
MultiByteToWideChar(CP_UTF8, 0, command, -1, openCommand, commandBufferLen);
|
||||
wcommand = openCommand;
|
||||
}
|
||||
|
||||
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];
|
||||
int app = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, applicationId, -1, appId, 32);
|
||||
if (app <= 0)
|
||||
return;
|
||||
MultiByteToWideChar(CP_UTF8, 0, applicationId, -1, appId, 32);
|
||||
|
||||
wchar_t wSteamId[32];
|
||||
int steam = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, steamId, -1, wSteamId, 32);
|
||||
if (steam <= 0)
|
||||
return;
|
||||
MultiByteToWideChar(CP_UTF8, 0, steamId, -1, wSteamId, 32);
|
||||
|
||||
HKEY key;
|
||||
auto status = RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Valve\\Steam", 0, KEY_READ, &key);
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
add_library(EffectLib STATIC ${FILE_SOURCES})
|
||||
|
||||
target_link_libraries(EffectLib
|
||||
cryptopp-static
|
||||
mio
|
||||
lzo2
|
||||
)
|
||||
|
||||
GroupSourcesByFolder(EffectLib)
|
||||
|
||||
@@ -96,7 +96,7 @@ bool CEffectData::LoadScript(const char * c_szFileName)
|
||||
|
||||
bool CEffectData::LoadSoundScriptData(const char * c_szFileName)
|
||||
{
|
||||
NSound::TSoundDataVector SoundDataVector;
|
||||
TSoundDataVector SoundDataVector;
|
||||
|
||||
if (LoadSoundInformationPiece(c_szFileName, SoundDataVector))
|
||||
{
|
||||
@@ -164,7 +164,7 @@ CEffectMeshScript * CEffectData::GetMeshPointer(DWORD dwPosition)
|
||||
return m_MeshVector[dwPosition];
|
||||
}
|
||||
|
||||
NSound::TSoundInstanceVector * CEffectData::GetSoundInstanceVector()
|
||||
TSoundInstanceVector * CEffectData::GetSoundInstanceVector()
|
||||
{
|
||||
return &m_SoundInstanceVector;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "AudioLib/Type.h"
|
||||
#include "../milesLib/Type.h"
|
||||
|
||||
#include "ParticleSystemData.h"
|
||||
#include "EffectMesh.h"
|
||||
@@ -30,7 +30,7 @@ class CEffectData
|
||||
DWORD GetLightCount();
|
||||
CLightData * GetLightPointer(DWORD dwPosition);
|
||||
|
||||
NSound::TSoundInstanceVector * GetSoundInstanceVector();
|
||||
TSoundInstanceVector * GetSoundInstanceVector();
|
||||
|
||||
float GetBoundingSphereRadius();
|
||||
D3DXVECTOR3 GetBoundingSpherePosition();
|
||||
@@ -52,7 +52,7 @@ class CEffectData
|
||||
TParticleVector m_ParticleVector;
|
||||
TMeshVector m_MeshVector;
|
||||
TLightVector m_LightVector;
|
||||
NSound::TSoundInstanceVector m_SoundInstanceVector;
|
||||
TSoundInstanceVector m_SoundInstanceVector;
|
||||
|
||||
float m_fBoundingSphereRadius;
|
||||
D3DXVECTOR3 m_v3BoundingSpherePosition;
|
||||
|
||||
@@ -90,14 +90,6 @@ void CEffectElementBaseInstance::Destroy()
|
||||
}
|
||||
|
||||
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()
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
#include "ParticleSystemInstance.h"
|
||||
#include "SimpleLightInstance.h"
|
||||
|
||||
#include "EterBase/Stl.h"
|
||||
#include "EterLib/StateManager.h"
|
||||
#include "AudioLib/SoundEngine.h"
|
||||
#include "../eterBase/Stl.h"
|
||||
#include "../eterLib/StateManager.h"
|
||||
#include "../MilesLib/SoundManager.h"
|
||||
|
||||
CDynamicPool<CEffectInstance> CEffectInstance::ms_kPool;
|
||||
int CEffectInstance::ms_iRenderingEffectCount = 0;
|
||||
@@ -50,12 +50,12 @@ void CEffectInstance::UpdateSound()
|
||||
{
|
||||
if (m_pSoundInstanceVector)
|
||||
{
|
||||
SoundEngine::Instance().UpdateSoundInstance(m_matGlobal._41,
|
||||
m_matGlobal._42,
|
||||
m_matGlobal._43,
|
||||
m_dwFrame,
|
||||
m_pSoundInstanceVector,
|
||||
false);
|
||||
UpdateSoundInstance(m_dwFrame,
|
||||
*m_pSoundInstanceVector,
|
||||
m_matGlobal._41,
|
||||
m_matGlobal._42,
|
||||
m_matGlobal._43,
|
||||
false);
|
||||
// NOTE : 매트릭스에서 위치를 직접 얻어온다 - [levites]
|
||||
}
|
||||
++m_dwFrame;
|
||||
@@ -80,7 +80,11 @@ void CEffectInstance::OnUpdate()
|
||||
{
|
||||
Transform();
|
||||
|
||||
#ifdef WORLD_EDITOR
|
||||
FEffectUpdator f(CTimer::Instance().GetElapsedSecond());
|
||||
#else
|
||||
FEffectUpdator f(CTimer::Instance().GetCurrentSecond()-m_fLastTime);
|
||||
#endif
|
||||
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_LightInstanceVector.begin(), m_LightInstanceVector.end(),f);
|
||||
@@ -91,7 +95,7 @@ void CEffectInstance::OnUpdate()
|
||||
|
||||
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_MAGFILTER, D3DTEXF_NONE);
|
||||
@@ -102,19 +106,30 @@ void CEffectInstance::OnRender()
|
||||
STATEMANAGER.SaveRenderState(D3DRS_ALPHATESTENABLE, FALSE);
|
||||
STATEMANAGER.SaveRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
|
||||
STATEMANAGER.SaveRenderState(D3DRS_ZWRITEENABLE, FALSE);
|
||||
/////
|
||||
STATEMANAGER.SaveRenderState(D3DRS_LIGHTING, FALSE);
|
||||
|
||||
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);
|
||||
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
|
||||
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
|
||||
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
|
||||
|
||||
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
|
||||
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));
|
||||
|
||||
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));
|
||||
|
||||
/////
|
||||
STATEMANAGER.RestoreSamplerState(0, D3DSAMP_MINFILTER);
|
||||
STATEMANAGER.RestoreSamplerState(0, D3DSAMP_MAGFILTER);
|
||||
|
||||
@@ -124,6 +139,7 @@ void CEffectInstance::OnRender()
|
||||
STATEMANAGER.RestoreRenderState(D3DRS_ALPHATESTENABLE);
|
||||
STATEMANAGER.RestoreRenderState(D3DRS_CULLMODE);
|
||||
STATEMANAGER.RestoreRenderState(D3DRS_ZWRITEENABLE);
|
||||
STATEMANAGER.RestoreRenderState(D3DRS_LIGHTING);
|
||||
|
||||
++ms_iRenderingEffectCount;
|
||||
}
|
||||
@@ -267,10 +283,18 @@ void CEffectInstance::Clear()
|
||||
__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()
|
||||
{
|
||||
ReleaseAlwaysHidden();
|
||||
|
||||
m_isAlive = FALSE;
|
||||
m_dwFrame = 0;
|
||||
m_pSoundInstanceVector = NULL;
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "UserInterface/Locale_inc.h"
|
||||
#include "Eterlib/GrpObjectInstance.h"
|
||||
#include "Eterlib/Pool.h"
|
||||
#include "AudioLib/Type.h"
|
||||
#include "Mileslib/Type.h"
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "EffectElementBaseInstance.h"
|
||||
#include "EffectData.h"
|
||||
#include "EffectMeshInstance.h"
|
||||
@@ -42,12 +41,6 @@ class CEffectInstance : public CGraphicObjectInstance
|
||||
bool LessRenderOrder(CEffectInstance* pkEftInst);
|
||||
|
||||
void SetEffectDataPointer(CEffectData * pEffectData);
|
||||
|
||||
// Returns the pointer to the effect data associated with this instance.
|
||||
CEffectData* GetEffectDataPointer() const
|
||||
{
|
||||
return m_pkEftData;
|
||||
}
|
||||
|
||||
void Clear();
|
||||
BOOL isAlive();
|
||||
@@ -62,6 +55,9 @@ class CEffectInstance : public CGraphicObjectInstance
|
||||
void OnRenderShadow() {} // Not used
|
||||
void OnRenderPCBlocker() {} // Not used
|
||||
|
||||
void BatchParticles();
|
||||
void RenderMeshes();
|
||||
|
||||
protected:
|
||||
void __Initialize();
|
||||
|
||||
@@ -84,7 +80,7 @@ class CEffectInstance : public CGraphicObjectInstance
|
||||
std::vector<CEffectMeshInstance*> m_MeshInstanceVector;
|
||||
std::vector<CLightInstance*> m_LightInstanceVector;
|
||||
|
||||
NSound::TSoundInstanceVector * m_pSoundInstanceVector;
|
||||
TSoundInstanceVector * m_pSoundInstanceVector;
|
||||
|
||||
float m_fBoundingSphereRadius;
|
||||
D3DXVECTOR3 m_v3BoundingSpherePosition;
|
||||
@@ -92,7 +88,6 @@ class CEffectInstance : public CGraphicObjectInstance
|
||||
float m_fLastTime;
|
||||
|
||||
public:
|
||||
|
||||
static CDynamicPool<CEffectInstance> ms_kPool;
|
||||
static int ms_iRenderingEffectCount;
|
||||
};
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
#include "StdAfx.h"
|
||||
#include "EterBase/Random.h"
|
||||
#include "Eterlib/StateManager.h"
|
||||
#include "../eterBase/Random.h"
|
||||
#include "../eterlib/StateManager.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)
|
||||
{
|
||||
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_kEftInstMap.size(),
|
||||
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()
|
||||
{
|
||||
STATEMANAGER.SetTexture(0, 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;
|
||||
TEffectInstanceMap::iterator i;
|
||||
for (i=rkMap_pkEftInstSrc.begin(); i!=rkMap_pkEftInstSrc.end(); ++i)
|
||||
s_kVct_pkEftInstSort.push_back(i->second);
|
||||
g_particleVertexBatch.clear();
|
||||
|
||||
std::sort(s_kVct_pkEftInstSort.begin(), s_kVct_pkEftInstSort.end(), CEffectManager_LessEffectInstancePtrRenderOrder());
|
||||
std::for_each(s_kVct_pkEftInstSort.begin(), s_kVct_pkEftInstSort.end(), CEffectManager_FEffectInstanceRender());
|
||||
}
|
||||
__RenderParticles();
|
||||
__RenderMeshes();
|
||||
}
|
||||
|
||||
BOOL CEffectManager::RegisterEffect(const char * c_szFileName,bool isExistDelete,bool isNeedCache)
|
||||
@@ -351,33 +318,6 @@ void CEffectManager::HideEffect()
|
||||
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)
|
||||
{
|
||||
TEffectDataMap::iterator itor = m_kEftDataMap.find(dwID);
|
||||
@@ -464,6 +404,122 @@ void CEffectManager::__DestroyEffectDataMap()
|
||||
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()
|
||||
{
|
||||
__DestroyEffectInstanceMap();
|
||||
@@ -489,26 +545,5 @@ CEffectManager::~CEffectManager()
|
||||
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
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "EffectInstance.h"
|
||||
|
||||
class CEffectManager : public CScreen, public CSingleton<CEffectManager>
|
||||
@@ -56,13 +55,6 @@ class CEffectManager : public CScreen, public CSingleton<CEffectManager>
|
||||
|
||||
void ShowEffect();
|
||||
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
|
||||
DWORD GetRandomEffect();
|
||||
@@ -77,9 +69,6 @@ class CEffectManager : public CScreen, public CSingleton<CEffectManager>
|
||||
|
||||
int GetRenderingEffectCount();
|
||||
|
||||
// Return the CRC of the effect-data for the selected effect instance.
|
||||
DWORD GetSelectedEffectDataCRC() const;
|
||||
|
||||
protected:
|
||||
void __Initialize();
|
||||
|
||||
@@ -87,6 +76,9 @@ class CEffectManager : public CScreen, public CSingleton<CEffectManager>
|
||||
void __DestroyEffectCacheMap();
|
||||
void __DestroyEffectDataMap();
|
||||
|
||||
void __RenderParticles();
|
||||
void __RenderMeshes();
|
||||
|
||||
protected:
|
||||
bool m_isDisableSortRendering;
|
||||
TEffectDataMap m_kEftDataMap;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "StdAfx.h"
|
||||
#include "Eterlib/StateManager.h"
|
||||
#include "Eterlib/ResourceManager.h"
|
||||
#include "PackLib/PackManager.h"
|
||||
#include "../eterlib/StateManager.h"
|
||||
#include "../eterlib/ResourceManager.h"
|
||||
#include "../eterpack/EterPackManager.h"
|
||||
#include "EffectMesh.h"
|
||||
|
||||
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"))
|
||||
{
|
||||
TPackFile File;
|
||||
LPCVOID pMotionData;
|
||||
CMappedFile File;
|
||||
|
||||
if (CPackManager::Instance().GetFile(pMeshData->szDiffuseMapFileName, File))
|
||||
if (CEterPackManager::Instance().Get(File, pMeshData->szDiffuseMapFileName, &pMotionData))
|
||||
{
|
||||
CMemoryTextFileLoader textFileLoader;
|
||||
std::vector<std::string> stTokenVector;
|
||||
|
||||
textFileLoader.Bind(File.size(), File.data());
|
||||
textFileLoader.Bind(File.Size(), pMotionData);
|
||||
|
||||
std::string strPathName;
|
||||
GetOnlyPathName(pMeshData->szDiffuseMapFileName, strPathName);
|
||||
@@ -336,14 +337,15 @@ BOOL CEffectMesh::__LoadData_Ver001(int iSize, const BYTE * c_pbBuf)
|
||||
|
||||
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;
|
||||
std::vector<std::string> stTokenVector;
|
||||
|
||||
textFileLoader.Bind(File.size(), File.data());
|
||||
textFileLoader.Bind(File.Size(), pMotionData);
|
||||
|
||||
std::string strPathName;
|
||||
GetOnlyPathName(pMeshData->szDiffuseMapFileName, strPathName);
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
#include <d3dx9.h>
|
||||
|
||||
#include "Eterlib/GrpScreen.h"
|
||||
#include "Eterlib/Resource.h"
|
||||
#include "Eterlib/GrpImageInstance.h"
|
||||
#include "EterLib/TextFileLoader.h"
|
||||
#include "../eterlib/GrpScreen.h"
|
||||
#include "../eterlib/Resource.h"
|
||||
#include "../eterlib/GrpImageInstance.h"
|
||||
#include "../eterLib/TextFileLoader.h"
|
||||
|
||||
#include "Type.h"
|
||||
#include "EffectElementBase.h"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#include "StdAfx.h"
|
||||
#include "EterLib/StateManager.h"
|
||||
#include "EterLib/ResourceManager.h"
|
||||
#include "../eterLib/StateManager.h"
|
||||
#include "../eterLib/ResourceManager.h"
|
||||
#include "EffectMeshInstance.h"
|
||||
#include "Eterlib/GrpMath.h"
|
||||
#include "../eterlib/GrpMath.h"
|
||||
|
||||
CDynamicPool<CEffectMeshInstance> CEffectMeshInstance::ms_kPool;
|
||||
|
||||
@@ -167,8 +167,7 @@ void CEffectMeshInstance::OnRender()
|
||||
}
|
||||
|
||||
Color.a = fAlpha * rFrameData.fVisibility;
|
||||
STATEMANAGER.SetRenderState(D3DRS_TEXTUREFACTOR, DWORD(Color));
|
||||
STATEMANAGER.SetFVF(D3DFVF_XYZ | D3DFVF_TEX1);
|
||||
STATEMANAGER.SetRenderState(D3DRS_TEXTUREFACTOR, Color);
|
||||
STATEMANAGER.DrawPrimitiveUP(D3DPT_TRIANGLELIST,
|
||||
rFrameData.dwIndexCount/3,
|
||||
&rFrameData.PDTVertexVector[0],
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "Eterlib/GrpScreen.h"
|
||||
#include "Eterlib/GrpImageInstance.h"
|
||||
#include "../eterlib/GrpScreen.h"
|
||||
#include "../eterlib/GrpImageInstance.h"
|
||||
#include "EffectElementBaseInstance.h"
|
||||
#include "FrameController.h"
|
||||
#include "EffectMesh.h"
|
||||
|
||||
@@ -156,6 +156,12 @@ void CParticleInstance::UpdateColor(float time, float elapsedTime)
|
||||
return;
|
||||
|
||||
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)
|
||||
@@ -179,7 +185,10 @@ void CParticleInstance::UpdateAirResistance(float time, float elapsedTime)
|
||||
|
||||
void CParticleInstance::Transform(const D3DXMATRIX * c_matLocal)
|
||||
{
|
||||
#ifndef ENABLE_BATCHED_PARTICLE_RENDERING
|
||||
STATEMANAGER.SetRenderState(D3DRS_TEXTUREFACTOR, m_Color);
|
||||
#endif
|
||||
/////
|
||||
|
||||
D3DXVECTOR3 v3Up;
|
||||
D3DXVECTOR3 v3Cross;
|
||||
@@ -313,24 +322,63 @@ void CParticleInstance::Transform(const D3DXMATRIX * c_matLocal)
|
||||
{
|
||||
D3DXVECTOR3 v3Position;
|
||||
D3DXVec3TransformCoord(&v3Position, &m_v3Position, c_matLocal);
|
||||
m_ParticleMesh[0].position = v3Position - v3Up + v3Cross;
|
||||
m_ParticleMesh[1].position = v3Position - v3Up - v3Cross;
|
||||
m_ParticleMesh[2].position = v3Position + v3Up + v3Cross;
|
||||
m_ParticleMesh[3].position = v3Position + v3Up - v3Cross;
|
||||
|
||||
D3DXVECTOR3 p0 = v3Position - v3Up + v3Cross; // bottom-left
|
||||
D3DXVECTOR3 p1 = v3Position - v3Up - v3Cross; // bottom-right
|
||||
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
|
||||
{
|
||||
m_ParticleMesh[0].position = m_v3Position - v3Up + v3Cross;
|
||||
m_ParticleMesh[1].position = m_v3Position - v3Up - v3Cross;
|
||||
m_ParticleMesh[2].position = m_v3Position + v3Up + v3Cross;
|
||||
m_ParticleMesh[3].position = m_v3Position + v3Up - v3Cross;
|
||||
D3DXVECTOR3 p0 = m_v3Position - v3Up + v3Cross; // bottom-left
|
||||
D3DXVECTOR3 p1 = m_v3Position - v3Up - v3Cross; // bottom-right
|
||||
D3DXVECTOR3 p2 = m_v3Position + v3Up + v3Cross; // top-left
|
||||
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)
|
||||
{
|
||||
#ifndef ENABLE_BATCHED_PARTICLE_RENDERING
|
||||
STATEMANAGER.SetRenderState(D3DRS_TEXTUREFACTOR, m_Color);
|
||||
#endif
|
||||
|
||||
/////
|
||||
|
||||
D3DXVECTOR3 v3Up;
|
||||
D3DXVECTOR3 v3Cross;
|
||||
@@ -462,17 +510,52 @@ void CParticleInstance::Transform(const D3DXMATRIX * c_matLocal, const float c_f
|
||||
{
|
||||
D3DXVECTOR3 v3Position;
|
||||
D3DXVec3TransformCoord(&v3Position, &m_v3Position, c_matLocal);
|
||||
m_ParticleMesh[0].position = v3Position - v3Up + v3Cross;
|
||||
m_ParticleMesh[1].position = v3Position - v3Up - v3Cross;
|
||||
m_ParticleMesh[2].position = v3Position + v3Up + v3Cross;
|
||||
m_ParticleMesh[3].position = v3Position + v3Up - v3Cross;
|
||||
|
||||
D3DXVECTOR3 p0 = v3Position - v3Up + v3Cross; // bottom-left
|
||||
D3DXVECTOR3 p1 = v3Position - v3Up - v3Cross; // bottom-right
|
||||
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
|
||||
{
|
||||
m_ParticleMesh[0].position = m_v3Position - v3Up + v3Cross;
|
||||
m_ParticleMesh[1].position = m_v3Position - v3Up - v3Cross;
|
||||
m_ParticleMesh[2].position = m_v3Position + v3Up + v3Cross;
|
||||
m_ParticleMesh[3].position = m_v3Position + v3Up - v3Cross;
|
||||
D3DXVECTOR3 p0 = m_v3Position - v3Up + v3Cross; // bottom-left
|
||||
D3DXVECTOR3 p1 = m_v3Position - v3Up - v3Cross; // bottom-right
|
||||
D3DXVECTOR3 p2 = m_v3Position + v3Up + v3Cross; // top-left
|
||||
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_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_rotationType = CParticleProperty::ROTATION_TYPE_NONE;
|
||||
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[1].texCoord = D3DXVECTOR2(0.0f, 0.0f);
|
||||
m_ParticleMesh[2].texCoord = D3DXVECTOR2(1.0f, 1.0f);
|
||||
m_ParticleMesh[3].texCoord = D3DXVECTOR2(1.0f, 0.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
CParticleInstance::CParticleInstance()
|
||||
@@ -510,7 +608,11 @@ CParticleInstance::~CParticleInstance()
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
#pragma once
|
||||
#include "UserInterface/Locale_inc.h"
|
||||
#include "Type.h"
|
||||
#include "Eterlib/GrpBase.h"
|
||||
#include "EterLib/Pool.h"
|
||||
|
||||
#include <array>
|
||||
|
||||
class CParticleProperty;
|
||||
class CEmitterProperty;
|
||||
|
||||
@@ -38,6 +41,7 @@ class CParticleInstance
|
||||
D3DXVECTOR2 m_v2Scale;
|
||||
|
||||
float m_fRotation;
|
||||
|
||||
D3DXCOLOR m_Color;
|
||||
|
||||
BYTE m_byTextureAnimationType;
|
||||
@@ -64,7 +68,11 @@ class CParticleInstance
|
||||
void Transform(const D3DXMATRIX * c_matLocal=NULL);
|
||||
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();
|
||||
|
||||
@@ -72,7 +80,12 @@ class CParticleInstance
|
||||
|
||||
protected:
|
||||
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:
|
||||
static CDynamicPool<CParticleInstance> ms_kPool;
|
||||
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
#include "StdAfx.h"
|
||||
#include "ParticleProperty.h"
|
||||
#include "Eterlib/ResourceManager.h"
|
||||
#include "../eterlib/ResourceManager.h"
|
||||
|
||||
void CParticleProperty::InsertTexture(const char * c_szFileName)
|
||||
{
|
||||
CGraphicImage * pImage = (CGraphicImage *)CResourceManager::Instance().GetResourcePointer(c_szFileName);
|
||||
|
||||
m_ImageVector.push_back(pImage);
|
||||
#ifdef WORLD_EDITOR
|
||||
m_TextureNameVector.push_back(c_szFileName);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool CParticleProperty::SetTexture(const char * c_szFileName)
|
||||
@@ -16,6 +20,9 @@ bool CParticleProperty::SetTexture(const char * c_szFileName)
|
||||
return false;
|
||||
}
|
||||
m_ImageVector.clear();
|
||||
#ifdef WORLD_EDITOR
|
||||
m_TextureNameVector.clear();
|
||||
#endif
|
||||
InsertTexture(c_szFileName);
|
||||
return true;
|
||||
}
|
||||
@@ -49,7 +56,15 @@ void CParticleProperty::Clear()
|
||||
m_TimeEventScaleX.clear();
|
||||
m_TimeEventScaleY.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();
|
||||
#endif
|
||||
m_TimeEventRotation.clear();
|
||||
|
||||
m_ImageVector.clear();
|
||||
@@ -88,7 +103,16 @@ CParticleProperty & CParticleProperty::operator = ( const CParticleProperty& c_P
|
||||
m_TimeEventScaleX = c_ParticleProperty.m_TimeEventScaleX;
|
||||
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;
|
||||
#endif
|
||||
m_TimeEventRotation = c_ParticleProperty.m_TimeEventRotation;
|
||||
|
||||
m_ImageVector = c_ParticleProperty.m_ImageVector;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "Eterlib/GrpImageInstance.h"
|
||||
#include "../eterlib/GrpImageInstance.h"
|
||||
|
||||
#include "Type.h"
|
||||
|
||||
@@ -75,7 +75,16 @@ class CParticleProperty
|
||||
|
||||
TTimeEventTableFloat m_TimeEventScaleX;
|
||||
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;
|
||||
#endif
|
||||
TTimeEventTableFloat m_TimeEventRotation;
|
||||
|
||||
std::vector<CGraphicImage*> m_ImageVector;
|
||||
|
||||
@@ -210,6 +210,17 @@ BOOL CParticleSystemData::OnLoadScript(CTextFileLoader & rTextFileLoader)
|
||||
if (!GetTokenTimeEventFloat(rTextFileLoader, "timeeventscaley", &m_ParticleProperty.m_TimeEventScaleY))
|
||||
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 TimeEventB;
|
||||
TTimeEventTableFloat TimeEventG;
|
||||
@@ -246,13 +257,16 @@ BOOL CParticleSystemData::OnLoadScript(CTextFileLoader & rTextFileLoader)
|
||||
fA = GetTimeEventBlendValue(fTime, TimeEventA);
|
||||
TTimeEventTypeColor t;
|
||||
t.m_fTime = fTime;
|
||||
t.m_Value.r = fR;
|
||||
t.m_Value.g = fG;
|
||||
t.m_Value.b = fB;
|
||||
t.m_Value.a = fA;
|
||||
D3DXCOLOR c;
|
||||
c.r = fR;
|
||||
c.g = fG;
|
||||
c.b = fB;
|
||||
c.a = fA;
|
||||
t.m_Value = c;
|
||||
m_ParticleProperty.m_TimeEventColor.push_back(t);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!GetTokenTimeEventFloat(rTextFileLoader, "timeeventrotation", &m_ParticleProperty.m_TimeEventRotation))
|
||||
return FALSE;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "EterLib/TextFileLoader.h"
|
||||
#include "../eterLib/TextFileLoader.h"
|
||||
|
||||
#include "EffectElementBase.h"
|
||||
#include "EmitterProperty.h"
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
#include "StdAfx.h"
|
||||
#include "EterBase/Random.h"
|
||||
#include "EterLib/StateManager.h"
|
||||
#include "../eterBase/Random.h"
|
||||
#include "../eterLib/StateManager.h"
|
||||
#include "ParticleSystemData.h"
|
||||
#include "ParticleSystemInstance.h"
|
||||
#include "ParticleInstance.h"
|
||||
|
||||
std::unordered_map<LPDIRECT3DTEXTURE9, std::unordered_map<uint32_t, std::vector<TPDTVertex>>> g_particleVertexBatch;
|
||||
|
||||
CDynamicPool<CParticleSystemInstance> CParticleSystemInstance::ms_kPool;
|
||||
|
||||
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.y= m_pParticleProperty->m_TimeEventScaleY.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;
|
||||
#endif
|
||||
}
|
||||
|
||||
m_ParticleInstanceListVector[pInstance->m_byFrameIndex].push_back(pInstance);
|
||||
@@ -336,80 +345,111 @@ namespace NParticleRenderer
|
||||
struct TwoSideRenderer
|
||||
{
|
||||
const D3DXMATRIX * pmat;
|
||||
TwoSideRenderer(const D3DXMATRIX * pmat=NULL)
|
||||
: pmat(pmat)
|
||||
uint32_t opKey;
|
||||
|
||||
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));
|
||||
STATEMANAGER.DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, pInstance->GetParticleMeshPointer(), sizeof(TPTVertex));
|
||||
vtxBatch.insert(vtxBatch.end(), particleMesh.begin(), particleMesh.end());
|
||||
|
||||
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
|
||||
{
|
||||
const D3DXMATRIX * pmat;
|
||||
ThreeSideRenderer(const D3DXMATRIX * pmat=NULL)
|
||||
: pmat(pmat)
|
||||
uint32_t opKey;
|
||||
|
||||
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);
|
||||
STATEMANAGER.DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, pInstance->GetParticleMeshPointer(), sizeof(TPTVertex));
|
||||
vtxBatch.insert(vtxBatch.end(), particleMesh.begin(), particleMesh.end());
|
||||
|
||||
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));
|
||||
STATEMANAGER.DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, pInstance->GetParticleMeshPointer(), sizeof(TPTVertex));
|
||||
vtxBatch.insert(vtxBatch.end(), particleMesh.begin(), particleMesh.end());
|
||||
}
|
||||
};
|
||||
|
||||
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();
|
||||
STATEMANAGER.DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, pInstance->GetParticleMeshPointer(), sizeof(TPTVertex));
|
||||
vtxBatch.insert(vtxBatch.end(), particleMesh.begin(), particleMesh.end());
|
||||
}
|
||||
};
|
||||
struct AttachRenderer
|
||||
{
|
||||
const D3DXMATRIX* pmat;
|
||||
AttachRenderer(const D3DXMATRIX * pmat)
|
||||
: pmat(pmat)
|
||||
uint32_t opKey;
|
||||
|
||||
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);
|
||||
STATEMANAGER.DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, pInstance->GetParticleMeshPointer(), sizeof(TPTVertex));
|
||||
vtxBatch.insert(vtxBatch.end(), particleMesh.begin(), particleMesh.end());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void CParticleSystemInstance::OnRender()
|
||||
{
|
||||
g_particleVertexBatch.clear();
|
||||
|
||||
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();
|
||||
auto obj = NParticleRenderer::NormalRenderer(opKey);
|
||||
ForEachParticleRendering(obj);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto obj = NParticleRenderer::AttachRenderer(mc_pmatLocal);
|
||||
auto obj = NParticleRenderer::AttachRenderer(opKey, mc_pmatLocal);
|
||||
ForEachParticleRendering(obj);
|
||||
}
|
||||
}
|
||||
@@ -417,12 +457,12 @@ void CParticleSystemInstance::OnRender()
|
||||
{
|
||||
if (!m_pParticleProperty->m_bAttachFlag)
|
||||
{
|
||||
auto obj = NParticleRenderer::TwoSideRenderer();
|
||||
auto obj = NParticleRenderer::TwoSideRenderer(opKey);
|
||||
ForEachParticleRendering(obj);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto obj = NParticleRenderer::TwoSideRenderer(mc_pmatLocal);
|
||||
auto obj = NParticleRenderer::TwoSideRenderer(opKey, mc_pmatLocal);
|
||||
ForEachParticleRendering(obj);
|
||||
}
|
||||
}
|
||||
@@ -430,12 +470,90 @@ void CParticleSystemInstance::OnRender()
|
||||
{
|
||||
if (!m_pParticleProperty->m_bAttachFlag)
|
||||
{
|
||||
auto obj = NParticleRenderer::ThreeSideRenderer();
|
||||
auto obj = NParticleRenderer::ThreeSideRenderer(opKey);
|
||||
ForEachParticleRendering(obj);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#pragma once
|
||||
#include "UserInterface/Locale_inc.h"
|
||||
#include "EffectElementBaseInstance.h"
|
||||
#include "ParticleInstance.h"
|
||||
#include "ParticleProperty.h"
|
||||
@@ -25,14 +26,12 @@ class CParticleSystemInstance : public CEffectElementBaseInstance
|
||||
DWORD 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();
|
||||
for (; itor != m_ParticleInstanceListVector[dwFrameIndex].end(); ++itor)
|
||||
{
|
||||
if (!InFrustum(*itor))
|
||||
continue;
|
||||
|
||||
FunObj(*itor);
|
||||
return;
|
||||
FunObj(*itor, m_kVct_pkImgInst[dwFrameIndex]->GetTextureReference().GetD3DTexture());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -58,6 +57,8 @@ class CParticleSystemInstance : public CEffectElementBaseInstance
|
||||
|
||||
DWORD GetEmissionCount();
|
||||
|
||||
void BatchParticles();
|
||||
|
||||
protected:
|
||||
void OnInitialize();
|
||||
void OnDestroy();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "Stdafx.h"
|
||||
#include "EterLib/GrpLightManager.h"
|
||||
#include "../eterLib/GrpLightManager.h"
|
||||
|
||||
#include "SimpleLightInstance.h"
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "EterLib/GrpScreen.h"
|
||||
#include "../eterLib/GrpScreen.h"
|
||||
|
||||
#include "EffectElementBaseInstance.h"
|
||||
#include "SimpleLightData.h"
|
||||
|
||||
@@ -2,19 +2,17 @@
|
||||
|
||||
//#include <crtdbg.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 "../eterBase/StdAfx.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"
|
||||
|
||||
@@ -74,8 +74,8 @@ enum EBillBoardType
|
||||
|
||||
BILLBOARD_TYPE_LIE, // 바닥에 누은 형상
|
||||
|
||||
BILLBOARD_TYPE_2FACE, // / and
|
||||
BILLBOARD_TYPE_3FACE, // / and
|
||||
BILLBOARD_TYPE_2FACE, // / and \
|
||||
BILLBOARD_TYPE_3FACE, // / and \ and -
|
||||
|
||||
//BILLBOARD_TYPE_RAY, // 잔상
|
||||
|
||||
@@ -123,6 +123,68 @@ typedef struct SEffectPosition : public CTimeEvent<D3DXVECTOR3>
|
||||
D3DXVECTOR3 m_vecControlPoint;
|
||||
} 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<short> TTimeEventTypeShort;
|
||||
typedef CTimeEvent<float> TTimeEventTypeFloat;
|
||||
@@ -176,6 +238,14 @@ inline D3DXVECTOR3 BlendSingleValue(float time, const TEffectPosition& low, cons
|
||||
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>
|
||||
auto GetTimeEventBlendValue(float time,
|
||||
const std::vector<T>& vec) -> typename T::value_type
|
||||
|
||||
@@ -5,7 +5,6 @@ add_library(EterBase STATIC ${FILE_SOURCES})
|
||||
target_link_libraries(EterBase
|
||||
lzo2
|
||||
cryptopp-static
|
||||
mio
|
||||
)
|
||||
|
||||
GroupSourcesByFolder(EterBase)
|
||||
|
||||
299
src/EterBase/CPostIt.cpp
Normal file
299
src/EterBase/CPostIt.cpp
Normal 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
80
src/EterBase/CPostIt.h
Normal 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_ */
|
||||
@@ -1,8 +1,6 @@
|
||||
#include "StdAfx.h"
|
||||
#include "CRC32.h"
|
||||
|
||||
#include <utf8.h>
|
||||
|
||||
static unsigned long CRCTable[256] =
|
||||
{
|
||||
0x00000000,0x77073096,0xEE0E612C,0x990951BA,0x076DC419,0x706AF48F,
|
||||
@@ -149,55 +147,65 @@ DWORD GetHFILECRC32(HANDLE hFile)
|
||||
dataOffset + mapSize, // low
|
||||
NULL); // name
|
||||
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)
|
||||
{
|
||||
//tw1x1: If MapViewOfFile returns null, crash risk on mapping failure
|
||||
dwRetCRC32 = GetCRC32((const char*)lpMapData, dwFileSize);
|
||||
|
||||
UnmapViewOfFile(lpMapData);
|
||||
}
|
||||
|
||||
CloseHandle(hFM);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
HANDLE hFile = CreateFileW(c_szFileName, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
if (hFile == INVALID_HANDLE_VALUE)
|
||||
return 0;
|
||||
|
||||
DWORD dwRetCRC32 = GetHFILECRC32(hFile);
|
||||
|
||||
DWORD dwRetCRC32=GetHFILECRC32(hFile);
|
||||
|
||||
CloseHandle(hFile);
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
|
||||
std::wstring wFile = Utf8ToWide(std::string(c_szFileName));
|
||||
HANDLE hFile = CreateFileW(wFile.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
DWORD dwSize = GetFileSize(hFile, NULL);
|
||||
|
||||
if (hFile == INVALID_HANDLE_VALUE)
|
||||
return 0;
|
||||
|
||||
DWORD dwSize = ::GetFileSize(hFile, nullptr);
|
||||
CloseHandle(hFile);
|
||||
|
||||
return dwSize;
|
||||
}
|
||||
|
||||
@@ -6,8 +6,7 @@
|
||||
DWORD GetCRC32(const char* buffer, size_t count);
|
||||
DWORD GetCaseCRC32(const char * buf, size_t len);
|
||||
DWORD GetHFILECRC32(HANDLE hFile);
|
||||
DWORD GetFileCRC32(const wchar_t* c_szFileName);
|
||||
DWORD GetFileCRC32(const char* fileUtf8);
|
||||
DWORD GetFileCRC32(const char* c_szFileName);
|
||||
DWORD GetFileSize(const char* c_szFileName);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2,266 +2,237 @@
|
||||
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string>
|
||||
|
||||
#include "Debug.h"
|
||||
#include "Singleton.h"
|
||||
#include "Timer.h"
|
||||
#include <filesystem>
|
||||
#include <utf8.h>
|
||||
|
||||
const DWORD DEBUG_STRING_MAX_LEN = 1024;
|
||||
|
||||
static int isLogFile = false;
|
||||
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>
|
||||
{
|
||||
public:
|
||||
CLogFile() : m_fp(NULL) {}
|
||||
public:
|
||||
CLogFile() : m_fp(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~CLogFile()
|
||||
{
|
||||
if (m_fp)
|
||||
fclose(m_fp);
|
||||
virtual ~CLogFile()
|
||||
{
|
||||
if (m_fp)
|
||||
fclose(m_fp);
|
||||
|
||||
m_fp = NULL;
|
||||
}
|
||||
m_fp = NULL;
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
m_fp = fopen("log/log.txt", "w");
|
||||
}
|
||||
void Initialize()
|
||||
{
|
||||
m_fp = fopen("log.txt", "w");
|
||||
}
|
||||
|
||||
void Write(const char* c_pszMsg)
|
||||
{
|
||||
if (!m_fp)
|
||||
return;
|
||||
void Write(const char * c_pszMsg)
|
||||
{
|
||||
if (!m_fp)
|
||||
return;
|
||||
|
||||
time_t ct = time(0);
|
||||
struct tm ctm = *localtime(&ct);
|
||||
time_t ct = time(0);
|
||||
struct tm ctm = *localtime(&ct);
|
||||
|
||||
fprintf(m_fp, "%02d%02d %02d:%02d:%05d :: %s",
|
||||
ctm.tm_mon + 1,
|
||||
ctm.tm_mday,
|
||||
ctm.tm_hour,
|
||||
ctm.tm_min,
|
||||
ELTimer_GetMSec() % 60000,
|
||||
c_pszMsg);
|
||||
fprintf(m_fp, "%02d%02d %02d:%02d:%05d :: %s",
|
||||
ctm.tm_mon + 1,
|
||||
ctm.tm_mday,
|
||||
ctm.tm_hour,
|
||||
ctm.tm_min,
|
||||
ELTimer_GetMSec() % 60000,
|
||||
c_pszMsg);
|
||||
|
||||
fflush(m_fp);
|
||||
}
|
||||
fflush(m_fp);
|
||||
}
|
||||
|
||||
protected:
|
||||
FILE* m_fp;
|
||||
protected:
|
||||
FILE * m_fp;
|
||||
};
|
||||
|
||||
static CLogFile gs_logfile;
|
||||
|
||||
static UINT gs_uLevel = 0;
|
||||
static UINT gs_uLevel=0;
|
||||
|
||||
void SetLogLevel(UINT uLevel)
|
||||
{
|
||||
gs_uLevel = uLevel;
|
||||
gs_uLevel=uLevel;
|
||||
}
|
||||
|
||||
void Log(UINT uLevel, const char* c_szMsg)
|
||||
{
|
||||
if (uLevel >= gs_uLevel)
|
||||
Trace(c_szMsg);
|
||||
if (uLevel>=gs_uLevel)
|
||||
Trace(c_szMsg);
|
||||
}
|
||||
|
||||
void Logn(UINT uLevel, const char* c_szMsg)
|
||||
{
|
||||
if (uLevel >= gs_uLevel)
|
||||
Tracen(c_szMsg);
|
||||
if (uLevel>=gs_uLevel)
|
||||
Tracen(c_szMsg);
|
||||
}
|
||||
|
||||
void Logf(UINT uLevel, const char* c_szFormat, ...)
|
||||
{
|
||||
if (uLevel < gs_uLevel)
|
||||
return;
|
||||
|
||||
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);
|
||||
if (uLevel<gs_uLevel)
|
||||
return;
|
||||
|
||||
char szBuf[DEBUG_STRING_MAX_LEN+1];
|
||||
|
||||
va_list args;
|
||||
va_start(args, c_szFormat);
|
||||
_vsnprintf(szBuf, sizeof(szBuf), c_szFormat, args);
|
||||
va_end(args);
|
||||
#ifdef _DEBUG
|
||||
DBG_OUT_W_UTF8(szBuf);
|
||||
fputs(szBuf, stdout);
|
||||
OutputDebugString(szBuf);
|
||||
fputs(szBuf, stdout);
|
||||
#endif
|
||||
|
||||
if (isLogFile)
|
||||
LogFile(szBuf);
|
||||
if (isLogFile)
|
||||
LogFile(szBuf);
|
||||
}
|
||||
|
||||
void Lognf(UINT uLevel, const char* c_szFormat, ...)
|
||||
{
|
||||
if (uLevel < gs_uLevel)
|
||||
return;
|
||||
if (uLevel<gs_uLevel)
|
||||
return;
|
||||
|
||||
char szBuf[DEBUG_STRING_MAX_LEN + 2];
|
||||
va_list args;
|
||||
va_start(args, c_szFormat);
|
||||
|
||||
va_list args;
|
||||
va_start(args, c_szFormat);
|
||||
_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';
|
||||
}
|
||||
char szBuf[DEBUG_STRING_MAX_LEN+2];
|
||||
int len = _vsnprintf(szBuf, sizeof(szBuf)-1, c_szFormat, args);
|
||||
|
||||
if (len > 0)
|
||||
{
|
||||
szBuf[len] = '\n';
|
||||
szBuf[len + 1] = '\0';
|
||||
}
|
||||
va_end(args);
|
||||
#ifdef _DEBUG
|
||||
DBG_OUT_W_UTF8(szBuf);
|
||||
fputs(szBuf, stdout);
|
||||
OutputDebugString(szBuf);
|
||||
puts(szBuf);
|
||||
#endif
|
||||
|
||||
if (isLogFile)
|
||||
LogFile(szBuf);
|
||||
if (isLogFile)
|
||||
LogFile(szBuf);
|
||||
}
|
||||
|
||||
void Trace(const char* c_szMsg)
|
||||
|
||||
void Trace(const char * c_szMsg)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
DBG_OUT_W_UTF8(c_szMsg);
|
||||
printf("%s", c_szMsg ? c_szMsg : "");
|
||||
OutputDebugString(c_szMsg);
|
||||
printf("%s", c_szMsg);
|
||||
#endif
|
||||
|
||||
if (isLogFile)
|
||||
LogFile(c_szMsg ? c_szMsg : "");
|
||||
if (isLogFile)
|
||||
LogFile(c_szMsg);
|
||||
}
|
||||
|
||||
void Tracen(const char* c_szMsg)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
char szBuf[DEBUG_STRING_MAX_LEN + 2];
|
||||
_snprintf_s(szBuf, sizeof(szBuf), _TRUNCATE, "%s\n", c_szMsg ? c_szMsg : "");
|
||||
char szBuf[DEBUG_STRING_MAX_LEN+1];
|
||||
_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);
|
||||
|
||||
if (isLogFile)
|
||||
LogFile(szBuf);
|
||||
puts(c_szMsg);
|
||||
putc('\n', stdout);
|
||||
#else
|
||||
if (isLogFile)
|
||||
{
|
||||
LogFile(c_szMsg ? c_szMsg : "");
|
||||
LogFile("\n");
|
||||
}
|
||||
if (isLogFile)
|
||||
{
|
||||
LogFile(c_szMsg);
|
||||
LogFile("\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Tracenf(const char* c_szFormat, ...)
|
||||
{
|
||||
char szBuf[DEBUG_STRING_MAX_LEN + 2];
|
||||
va_list args;
|
||||
va_start(args, c_szFormat);
|
||||
|
||||
va_list args;
|
||||
va_start(args, c_szFormat);
|
||||
_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';
|
||||
}
|
||||
char szBuf[DEBUG_STRING_MAX_LEN+2];
|
||||
int len = _vsnprintf(szBuf, sizeof(szBuf)-1, c_szFormat, args);
|
||||
|
||||
if (len > 0)
|
||||
{
|
||||
szBuf[len] = '\n';
|
||||
szBuf[len + 1] = '\0';
|
||||
}
|
||||
va_end(args);
|
||||
#ifdef _DEBUG
|
||||
DBG_OUT_W_UTF8(szBuf);
|
||||
fputs(szBuf, stdout);
|
||||
OutputDebugString(szBuf);
|
||||
printf("%s", szBuf);
|
||||
#endif
|
||||
|
||||
if (isLogFile)
|
||||
LogFile(szBuf);
|
||||
if (isLogFile)
|
||||
LogFile(szBuf);
|
||||
}
|
||||
|
||||
void Tracef(const char* c_szFormat, ...)
|
||||
{
|
||||
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
|
||||
DBG_OUT_W_UTF8(szBuf);
|
||||
fputs(szBuf, stdout);
|
||||
OutputDebugString(szBuf);
|
||||
fputs(szBuf, stdout);
|
||||
#endif
|
||||
|
||||
if (isLogFile)
|
||||
LogFile(szBuf);
|
||||
if (isLogFile)
|
||||
LogFile(szBuf);
|
||||
}
|
||||
|
||||
void TraceError(const char* c_szFormat, ...)
|
||||
{
|
||||
#ifndef _DISTRIBUTE
|
||||
char szBuf[DEBUG_STRING_MAX_LEN + 2];
|
||||
|
||||
strncpy_s(szBuf, sizeof(szBuf), "SYSERR: ", _TRUNCATE);
|
||||
int prefixLen = (int)strlen(szBuf);
|
||||
char szBuf[DEBUG_STRING_MAX_LEN+2];
|
||||
|
||||
va_list args;
|
||||
va_start(args, c_szFormat);
|
||||
_vsnprintf_s(szBuf + prefixLen, sizeof(szBuf) - prefixLen, _TRUNCATE, c_szFormat, args);
|
||||
va_end(args);
|
||||
strncpy(szBuf, "SYSERR: ", DEBUG_STRING_MAX_LEN);
|
||||
int len = strlen(szBuf);
|
||||
|
||||
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';
|
||||
}
|
||||
va_list args;
|
||||
va_start(args, c_szFormat);
|
||||
len = _vsnprintf(szBuf + len, sizeof(szBuf) - (len + 1), c_szFormat, args) + len;
|
||||
va_end(args);
|
||||
|
||||
time_t ct = time(0);
|
||||
struct tm ctm = *localtime(&ct);
|
||||
szBuf[len] = '\n';
|
||||
szBuf[len + 1] = '\0';
|
||||
|
||||
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);
|
||||
time_t ct = time(0);
|
||||
struct tm ctm = *localtime(&ct);
|
||||
|
||||
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
|
||||
DBG_OUT_W_UTF8(szBuf);
|
||||
fputs(szBuf, stdout);
|
||||
OutputDebugString(szBuf);
|
||||
fputs(szBuf, stdout);
|
||||
#endif
|
||||
|
||||
if (isLogFile)
|
||||
LogFile(szBuf);
|
||||
if (isLogFile)
|
||||
LogFile(szBuf);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -269,101 +240,87 @@ void TraceErrorWithoutEnter(const char* c_szFormat, ...)
|
||||
{
|
||||
#ifndef _DISTRIBUTE
|
||||
|
||||
char szBuf[DEBUG_STRING_MAX_LEN];
|
||||
char szBuf[DEBUG_STRING_MAX_LEN];
|
||||
|
||||
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);
|
||||
|
||||
time_t ct = time(0);
|
||||
struct tm ctm = *localtime(&ct);
|
||||
time_t ct = time(0);
|
||||
struct tm ctm = *localtime(&ct);
|
||||
|
||||
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);
|
||||
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
|
||||
DBG_OUT_W_UTF8(szBuf);
|
||||
fputs(szBuf, stdout);
|
||||
OutputDebugString(szBuf);
|
||||
fputs(szBuf, stdout);
|
||||
#endif
|
||||
|
||||
if (isLogFile)
|
||||
LogFile(szBuf);
|
||||
if (isLogFile)
|
||||
LogFile(szBuf);
|
||||
#endif
|
||||
}
|
||||
|
||||
void LogBoxf(const char* c_szFormat, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, c_szFormat);
|
||||
va_list args;
|
||||
va_start(args, c_szFormat);
|
||||
|
||||
char szBuf[2048];
|
||||
_vsnprintf_s(szBuf, sizeof(szBuf), _TRUNCATE, c_szFormat, args);
|
||||
char szBuf[2048];
|
||||
_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)
|
||||
hWnd = g_PopupHwnd;
|
||||
if (!hWnd)
|
||||
hWnd = g_PopupHwnd;
|
||||
|
||||
std::wstring wMsg = Utf8ToWide(c_szMsg ? c_szMsg : "");
|
||||
std::wstring wCaption = Utf8ToWide(c_szCaption ? c_szCaption : "LOG");
|
||||
|
||||
MessageBoxW(hWnd, wMsg.c_str(), wCaption.c_str(), MB_OK);
|
||||
|
||||
// Logging stays UTF-8
|
||||
Tracen(c_szMsg ? c_szMsg : "");
|
||||
MessageBox(hWnd, c_szMsg, c_szCaption ? c_szCaption : "LOG", MB_OK);
|
||||
Tracen(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_start(args, c_szMessage);
|
||||
va_list args;
|
||||
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];
|
||||
_vsnprintf_s(szBuf, sizeof(szBuf), _TRUNCATE, c_szMessage, args);
|
||||
|
||||
va_end(args);
|
||||
|
||||
CLogFile::Instance().Write(szBuf);
|
||||
CLogFile::Instance().Write(szBuf);
|
||||
}
|
||||
|
||||
void OpenLogFile(bool bUseLogFIle)
|
||||
{
|
||||
if (!std::filesystem::exists("log")) {
|
||||
std::filesystem::create_directory("log");
|
||||
}
|
||||
|
||||
#ifndef _DISTRIBUTE
|
||||
_wfreopen(L"log/syserr.txt", L"w", stderr);
|
||||
freopen("syserr.txt", "w", stderr);
|
||||
|
||||
if (bUseLogFIle)
|
||||
{
|
||||
isLogFile = true;
|
||||
CLogFile::Instance().Initialize();
|
||||
}
|
||||
if (bUseLogFIle)
|
||||
{
|
||||
isLogFile = true;
|
||||
CLogFile::Instance().Initialize();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void OpenConsoleWindow()
|
||||
{
|
||||
AllocConsole();
|
||||
AllocConsole();
|
||||
|
||||
_wfreopen(L"CONOUT$", L"a", stdout);
|
||||
_wfreopen(L"CONIN$", L"r", stdin);
|
||||
freopen("CONOUT$", "a", stdout);
|
||||
freopen("CONIN$", "r", stdin);
|
||||
}
|
||||
|
||||
@@ -38,9 +38,3 @@ extern HWND g_PopupHwnd;
|
||||
} \
|
||||
|
||||
#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
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
#include "StdAfx.h"
|
||||
#include "FileBase.h"
|
||||
|
||||
#include <utf8.h>
|
||||
|
||||
CFileBase::CFileBase() : m_hFile(NULL), m_dwSize(0)
|
||||
{
|
||||
}
|
||||
@@ -36,12 +34,9 @@ BOOL CFileBase::Create(const char* filename, EFileMode mode)
|
||||
{
|
||||
Destroy();
|
||||
|
||||
// Keep filename internally as UTF-8 (engine side)
|
||||
strncpy(m_filename, filename, MAX_PATH);
|
||||
m_filename[MAX_PATH - 1] = '\0';
|
||||
|
||||
DWORD dwMode;
|
||||
DWORD dwShareMode = FILE_SHARE_READ;
|
||||
DWORD dwMode, dwShareMode = FILE_SHARE_READ;
|
||||
|
||||
if (mode == FILEMODE_WRITE)
|
||||
{
|
||||
@@ -49,26 +44,19 @@ BOOL CFileBase::Create(const char* filename, EFileMode mode)
|
||||
dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
|
||||
}
|
||||
else
|
||||
{
|
||||
dwMode = GENERIC_READ;
|
||||
}
|
||||
|
||||
// UTF-8 -> UTF-16 conversion for WinAPI
|
||||
std::wstring wFilename = Utf8ToWide(filename);
|
||||
|
||||
m_hFile = CreateFileW(
|
||||
wFilename.c_str(), // UTF-16 path
|
||||
dwMode,
|
||||
dwShareMode,
|
||||
nullptr,
|
||||
(mode == FILEMODE_READ) ? OPEN_EXISTING : OPEN_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
nullptr
|
||||
);
|
||||
m_hFile = CreateFile(filename, // name of the file
|
||||
dwMode, // desired access
|
||||
dwShareMode, // share mode
|
||||
NULL, // security attributes
|
||||
mode == FILEMODE_READ ? OPEN_EXISTING : OPEN_ALWAYS, // creation disposition
|
||||
FILE_ATTRIBUTE_NORMAL, // flags and attr
|
||||
NULL); // template file
|
||||
|
||||
if (m_hFile != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
m_dwSize = GetFileSize(m_hFile, nullptr);
|
||||
m_dwSize = GetFileSize(m_hFile, NULL);
|
||||
m_mode = mode;
|
||||
return true;
|
||||
}
|
||||
@@ -76,7 +64,7 @@ BOOL CFileBase::Create(const char* filename, EFileMode mode)
|
||||
/* char buf[256];
|
||||
GetCurrentDirectory(256, buf);
|
||||
DWORD dwErr = GetLastError();*/
|
||||
m_hFile = nullptr;
|
||||
m_hFile = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -107,7 +95,7 @@ BOOL CFileBase::Write(const void* src, int bytes)
|
||||
{
|
||||
DWORD dwUseless;
|
||||
BOOL ret = WriteFile(m_hFile, src, bytes, &dwUseless, NULL);
|
||||
|
||||
|
||||
if (!ret)
|
||||
return false;
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#include "StdAfx.h"
|
||||
#include "FileDir.h"
|
||||
#include <string>
|
||||
#include <utf8.h>
|
||||
|
||||
CDir::CDir()
|
||||
{
|
||||
@@ -21,46 +20,43 @@ void CDir::Destroy()
|
||||
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();
|
||||
|
||||
std::string stPath = c_szPath;
|
||||
|
||||
std::string stPath = c_szPath ? c_szPath : "";
|
||||
|
||||
if (!stPath.empty())
|
||||
if (stPath.length())
|
||||
{
|
||||
char end = stPath.back();
|
||||
char end = stPath[stPath.length() - 1];
|
||||
|
||||
if (end != '\\')
|
||||
stPath += '\\';
|
||||
stPath+='\\';
|
||||
}
|
||||
|
||||
// Query: UTF-8 -> UTF-16 for WinAPI
|
||||
std::string stQueryUtf8 = stPath + "*.*";
|
||||
std::wstring stQueryW = Utf8ToWide(stQueryUtf8);
|
||||
|
||||
m_wfd.dwFileAttributes = 0;
|
||||
std::string stQuery;
|
||||
stQuery += stPath;
|
||||
stQuery += "*.*";
|
||||
|
||||
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)
|
||||
return true;
|
||||
|
||||
do
|
||||
{
|
||||
// Convert filename to UTF-8 for existing logic/callbacks
|
||||
std::string fileNameUtf8 = WideToUtf8(m_wfd.cFileName);
|
||||
|
||||
if (!fileNameUtf8.empty() && fileNameUtf8[0] == '.')
|
||||
if (*m_wfd.cFileName == '.')
|
||||
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;
|
||||
}
|
||||
else
|
||||
{
|
||||
const char* c_szExtension = strchr(fileNameUtf8.c_str(), '.');
|
||||
const char * c_szExtension = strchr(m_wfd.cFileName, '.');
|
||||
if (!c_szExtension)
|
||||
continue;
|
||||
|
||||
@@ -69,29 +65,27 @@ bool CDir::Create(const char* c_szFilter, const char* c_szPath, BOOL bCheckedExt
|
||||
// 그전에 전 프로젝트의 CDir을 사용하는 곳에서 Extension을 "wav", "gr2" 이런식으로 넣게끔 한다. - [levites]
|
||||
if (bCheckedExtension)
|
||||
{
|
||||
std::string strFilter = c_szFilter ? c_szFilter : "";
|
||||
int iPos = (int)strFilter.find_first_of(';', 0);
|
||||
|
||||
std::string strFilter = c_szFilter;
|
||||
int iPos = strFilter.find_first_of(';', 0);
|
||||
if (iPos > 0)
|
||||
{
|
||||
std::string first = strFilter.substr(0, iPos);
|
||||
std::string second = strFilter.substr(iPos + 1);
|
||||
|
||||
if (0 != first.compare(c_szExtension + 1) &&
|
||||
0 != second.compare(c_szExtension + 1))
|
||||
std::string strFirstFilter = std::string(c_szFilter).substr(0, iPos);
|
||||
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))
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (0 != _stricmp(c_szExtension + 1, c_szFilter))
|
||||
if (0 != stricmp(c_szExtension+1, c_szFilter))
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!OnFile(stPath.c_str(), fileNameUtf8.c_str()))
|
||||
if (!OnFile(stPath.c_str(), m_wfd.cFileName))
|
||||
return false;
|
||||
}
|
||||
} while (FindNextFileW(m_hFind, &m_wfd));
|
||||
}
|
||||
while (FindNextFile(m_hFind, &m_wfd));
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -100,12 +94,12 @@ bool CDir::IsFolder()
|
||||
{
|
||||
if (m_wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
return true;
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void CDir::Initialize()
|
||||
{
|
||||
memset(&m_wfd, 0, sizeof(m_wfd));
|
||||
m_hFind = NULL;
|
||||
m_hFind = NULL;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#include "StdAfx.h"
|
||||
#include "FileLoader.h"
|
||||
#include <assert.h>
|
||||
#include <utf8.h>
|
||||
|
||||
CMemoryTextFileLoader::CMemoryTextFileLoader()
|
||||
{
|
||||
@@ -253,9 +252,7 @@ bool CDiskFileLoader::Open(const char* c_szFileName)
|
||||
if (!c_szFileName[0])
|
||||
return false;
|
||||
|
||||
// UTF-8 → UTF-16 conversion for Unicode path support
|
||||
std::wstring wFileName = Utf8ToWide(c_szFileName);
|
||||
m_fp = _wfopen(wFileName.c_str(), L"rb");
|
||||
m_fp = fopen(c_szFileName, "rb");
|
||||
|
||||
if (!m_fp)
|
||||
return false;
|
||||
|
||||
259
src/EterBase/MappedFile.cpp
Normal file
259
src/EterBase/MappedFile.cpp
Normal 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
59
src/EterBase/MappedFile.h
Normal 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
|
||||
6
src/EterBase/ServiceDefs.h
Normal file
6
src/EterBase/ServiceDefs.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef _EL_SERVICEDEFS_H_
|
||||
#define _EL_SERVICEDEFS_H_
|
||||
|
||||
#define _IMPROVED_PACKET_ENCRYPTION_
|
||||
|
||||
#endif //_EL_SERVICEDEFS_H_
|
||||
@@ -1,5 +1,10 @@
|
||||
#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:4786) // character 255 넘어가는거 끄기
|
||||
#pragma warning(disable:4244) // type conversion possible lose of data
|
||||
@@ -48,5 +53,4 @@
|
||||
|
||||
#include "vk.h"
|
||||
#include "filename.h"
|
||||
|
||||
#include "../UserInterface/Locale_inc.h"
|
||||
#include "ServiceDefs.h"
|
||||
|
||||
@@ -2,17 +2,11 @@
|
||||
#include "TempFile.h"
|
||||
#include "Utils.h"
|
||||
#include "Debug.h"
|
||||
#include <utf8.h>
|
||||
|
||||
CTempFile::~CTempFile()
|
||||
{
|
||||
Destroy();
|
||||
|
||||
if (m_szFileName[0])
|
||||
{
|
||||
std::wstring wPath = Utf8ToWide(m_szFileName);
|
||||
DeleteFileW(wPath.c_str());
|
||||
}
|
||||
DeleteFile(m_szFileName);
|
||||
}
|
||||
|
||||
CTempFile::CTempFile(const char * c_pszPrefix)
|
||||
|
||||
@@ -5,43 +5,24 @@
|
||||
#include <io.h>
|
||||
#include <assert.h>
|
||||
#include <sys/stat.h>
|
||||
#include <utf8.h>
|
||||
|
||||
#include "Utils.h"
|
||||
#include "filedir.h"
|
||||
|
||||
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]{};
|
||||
wchar_t wTempName[MAX_PATH + 1]{};
|
||||
GetTempPath(MAX_PATH, szTempPath);
|
||||
|
||||
// Get temp directory
|
||||
if (!GetTempPathW(MAX_PATH, wTempPath))
|
||||
return "";
|
||||
GetTempFileName(szTempPath, // directory for temp files
|
||||
c_pszPrefix ? c_pszPrefix : "etb", // temp file name prefix
|
||||
c_pszPrefix ? true : false, // create unique name
|
||||
szTempName); // buffer for name
|
||||
|
||||
// Prefix must be wide
|
||||
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();
|
||||
return (szTempName);
|
||||
}
|
||||
|
||||
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 == '.')
|
||||
{
|
||||
ext = pos;
|
||||
ext = pos;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (c == '/' || c == '\\')
|
||||
break;
|
||||
}
|
||||
@@ -102,7 +83,7 @@ void GetFileExtension(const char* c_szFile, int len, std::string* pstExt)
|
||||
char c=c_szFile[pos];
|
||||
if (ext==len && c=='.')
|
||||
{
|
||||
ext=pos;
|
||||
ext=pos;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -110,7 +91,7 @@ void GetFileExtension(const char* c_szFile, int len, std::string* pstExt)
|
||||
else if (c=='\\') break;
|
||||
}
|
||||
|
||||
++ext;
|
||||
++ext;
|
||||
if (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];
|
||||
if (ext==len && c=='.')
|
||||
{
|
||||
ext=pos;
|
||||
ext=pos;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -146,7 +127,7 @@ void GetFileNameParts(const char* c_szFile, int len, char* pszPath, char* pszNam
|
||||
else if (c=='\\') break;
|
||||
}
|
||||
|
||||
if (pos)
|
||||
if (pos)
|
||||
{
|
||||
++pos;
|
||||
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';
|
||||
}
|
||||
|
||||
++ext;
|
||||
++ext;
|
||||
if (len > ext)
|
||||
{
|
||||
int count = 0;
|
||||
@@ -182,10 +163,10 @@ void GetOldIndexingName(char * szName, int Index)
|
||||
{
|
||||
int dec, sign;
|
||||
char Temp[512];
|
||||
|
||||
|
||||
strcpy(Temp, _ecvt(Index, 256, &dec, &sign));
|
||||
Temp[dec] = '\0';
|
||||
|
||||
|
||||
strcat(szName, Temp);
|
||||
}
|
||||
|
||||
@@ -442,40 +423,38 @@ bool IsGlobalFileName(const char * c_szFileName)
|
||||
return strchr(c_szFileName, ':') != NULL;
|
||||
}
|
||||
|
||||
void MyCreateDirectory(const char* pathUtf8)
|
||||
void MyCreateDirectory(const char* path)
|
||||
{
|
||||
if (!pathUtf8 || !*pathUtf8)
|
||||
if (!path || !*path)
|
||||
return;
|
||||
|
||||
// Skip drive letter (C:\)
|
||||
const char* path = pathUtf8;
|
||||
if (strlen(path) >= 3 && path[1] == ':')
|
||||
path += 3;
|
||||
char * dir;
|
||||
const char * p;
|
||||
|
||||
size_t len = strlen(pathUtf8) + 1;
|
||||
char* dirUtf8 = new char[len];
|
||||
if (strlen(path) >= 3)
|
||||
{
|
||||
if (*(path + 1) == ':') // C:, D: 같은 경우를 체크
|
||||
path += 3;
|
||||
}
|
||||
|
||||
const char* p = path;
|
||||
p = path;
|
||||
|
||||
int len = strlen(path) + 1;
|
||||
dir = new char[len];
|
||||
|
||||
while (*p)
|
||||
{
|
||||
if (*p == '/' || *p == '\\')
|
||||
{
|
||||
memset(dirUtf8, 0, len);
|
||||
strncpy(dirUtf8, pathUtf8, p - path + (path - pathUtf8));
|
||||
|
||||
// UTF-8 → UTF-16 for WinAPI
|
||||
std::wstring wDir = Utf8ToWide(dirUtf8);
|
||||
CreateDirectoryW(wDir.c_str(), nullptr);
|
||||
memset(dir, 0, len);
|
||||
strncpy(dir, path, p - path);
|
||||
CreateDirectory(dir, NULL);
|
||||
}
|
||||
|
||||
++p;
|
||||
}
|
||||
|
||||
// Create final directory too
|
||||
std::wstring wFinal = Utf8ToWide(pathUtf8);
|
||||
CreateDirectoryW(wFinal.c_str(), nullptr);
|
||||
|
||||
delete[] dirUtf8;
|
||||
delete [] dir;
|
||||
}
|
||||
|
||||
class CDirRemover : public CDir
|
||||
@@ -505,31 +484,22 @@ class CDirRemover : public CDir
|
||||
ms_strDirectoryDeque.push_back(strWorkingFolder);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OnFile(const char* c_szPathName, const char* c_szFileName)
|
||||
{
|
||||
std::string strFullPathName;
|
||||
strFullPathName = c_szPathName;
|
||||
strFullPathName += c_szFileName;
|
||||
|
||||
std::wstring wFullPath = Utf8ToWide(strFullPathName);
|
||||
|
||||
// Make writable (use wide version)
|
||||
_wchmod(wFullPath.c_str(), _S_IWRITE);
|
||||
|
||||
// Delete (use wide WinAPI)
|
||||
DeleteFileW(wFullPath.c_str());
|
||||
strFullPathName += c_szFileName;
|
||||
_chmod(strFullPathName.c_str(), _S_IWRITE);
|
||||
DeleteFile(strFullPathName.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
static void RemoveAllDirectory()
|
||||
{
|
||||
for (std::deque<std::string>::iterator itor = ms_strDirectoryDeque.begin();
|
||||
itor != ms_strDirectoryDeque.end(); ++itor)
|
||||
for (std::deque<std::string>::iterator itor = ms_strDirectoryDeque.begin(); itor != ms_strDirectoryDeque.end(); ++itor)
|
||||
{
|
||||
const std::string& dirUtf8 = *itor;
|
||||
std::wstring wDir = Utf8ToWide(dirUtf8);
|
||||
RemoveDirectoryW(wDir.c_str());
|
||||
const std::string & c_rstrDirectory = *itor;
|
||||
RemoveDirectory(c_rstrDirectory.c_str());
|
||||
}
|
||||
|
||||
ms_strDirectoryDeque.clear();
|
||||
@@ -541,19 +511,14 @@ class CDirRemover : public CDir
|
||||
|
||||
std::deque<std::string> CDirRemover::ms_strDirectoryDeque;
|
||||
|
||||
void RemoveAllDirectory(const char* c_szDirectoryName)
|
||||
void RemoveAllDirectory(const char * c_szDirectoryName)
|
||||
{
|
||||
{
|
||||
CDirRemover remover;
|
||||
remover.Create("*.*", c_szDirectoryName);
|
||||
CDirRemover::RemoveAllDirectory();
|
||||
}
|
||||
|
||||
if (c_szDirectoryName && *c_szDirectoryName)
|
||||
{
|
||||
std::wstring wDir = Utf8ToWide(c_szDirectoryName);
|
||||
RemoveDirectoryW(wDir.c_str());
|
||||
}
|
||||
RemoveDirectory(c_szDirectoryName);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
wPath[MAX_PATH] = L'\0';
|
||||
GetModuleFileName(NULL, szPath, MAX_PATH);
|
||||
szPath[MAX_PATH] = '\0';
|
||||
|
||||
// Convert UTF-16 → UTF-8 for engine use
|
||||
r_str = WideToUtf8(wPath);
|
||||
r_str = szPath;
|
||||
}
|
||||
|
||||
const char * _getf(const char* c_szFormat, ...)
|
||||
|
||||
@@ -27,6 +27,12 @@
|
||||
|
||||
#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
|
||||
#define IS_SET(flag,bit) ((flag) & (bit))
|
||||
#endif
|
||||
@@ -209,18 +215,4 @@ void StringExceptCharacter(std::string * pstrString, const char * c_szCharacter)
|
||||
|
||||
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
|
||||
@@ -4,7 +4,6 @@
|
||||
#include <time.h>
|
||||
#include <winsock.h>
|
||||
#include <imagehlp.h>
|
||||
#include <utf8.h>
|
||||
|
||||
FILE* fException;
|
||||
|
||||
@@ -45,21 +44,18 @@ LONG __stdcall EterExceptionFilter(_EXCEPTION_POINTERS* pExceptionInfo)
|
||||
HANDLE hProcess = GetCurrentProcess();
|
||||
HANDLE hThread = GetCurrentThread();
|
||||
|
||||
fException = fopen("log/ErrorLog.txt", "wt");
|
||||
fException = fopen("ErrorLog.txt", "wt");
|
||||
if (fException)
|
||||
{
|
||||
wchar_t wModuleName[MAX_PATH]{};
|
||||
char module_name[256];
|
||||
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);
|
||||
|
||||
// Convert once for logging
|
||||
std::string moduleNameUtf8 = WideToUtf8(wModuleName);
|
||||
|
||||
fprintf(fException, "Module Name: %s\n", moduleNameUtf8.c_str());
|
||||
fprintf(fException, "Module Name: %s\n", module_name);
|
||||
fprintf(fException, "Time Stamp: 0x%08x - %s\n", (unsigned int)module_time, ctime(&module_time));
|
||||
fprintf(fException, "\n");
|
||||
fprintf(fException, "Exception Type: 0x%08x\n", pExceptionInfo->ExceptionRecord->ExceptionCode);
|
||||
|
||||
@@ -216,14 +216,22 @@ public:
|
||||
public:
|
||||
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)
|
||||
{
|
||||
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
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -231,12 +239,12 @@ public:
|
||||
{
|
||||
if (m_local_buf != m_buf)
|
||||
{
|
||||
dbg_printf("DecryptBuffer - FreeHeap\n");
|
||||
dbg_printf("DecruptBuffer - FreeHeap\n");
|
||||
delete [] m_buf;
|
||||
}
|
||||
else
|
||||
{
|
||||
dbg_printf("DecryptBuffer - FreeStack\n");
|
||||
dbg_printf("DecruptBuffer - FreeStack\n");
|
||||
}
|
||||
}
|
||||
void* GetBufferPtr()
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
add_library(EterGrnLib STATIC ${FILE_SOURCES})
|
||||
|
||||
target_link_libraries(EterGrnLib
|
||||
cryptopp-static
|
||||
mio
|
||||
lzo2
|
||||
)
|
||||
|
||||
GroupSourcesByFolder(EterGrnLib)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
@@ -58,10 +58,10 @@ static CGraphicVertexBuffer* __AllocDeformVertexBuffer(unsigned deformableVertex
|
||||
CGraphicVertexBuffer* pkNewVB = new CGraphicVertexBuffer;
|
||||
|
||||
if (!pkNewVB->Create(
|
||||
capacity,
|
||||
D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1,
|
||||
D3DUSAGE_DYNAMIC,
|
||||
D3DPOOL_DEFAULT))
|
||||
capacity,
|
||||
D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1,
|
||||
D3DUSAGE_WRITEONLY,
|
||||
D3DPOOL_MANAGED))
|
||||
{
|
||||
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;
|
||||
pkNewVB->Create(
|
||||
capacity,
|
||||
D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1,
|
||||
D3DUSAGE_DYNAMIC,
|
||||
D3DPOOL_DEFAULT);
|
||||
capacity,
|
||||
D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1,
|
||||
D3DUSAGE_WRITEONLY,
|
||||
D3DPOOL_MANAGED);
|
||||
gs_vbs[index].push_back(pkNewVB);
|
||||
}
|
||||
NANOEND
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
#include <windows.h>
|
||||
#include <d3d9.h>
|
||||
|
||||
#include "Eterlib/ReferenceObject.h"
|
||||
#include "Eterlib/Ref.h"
|
||||
#include "Eterlib/GrpImageInstance.h"
|
||||
#include "../eterlib/ReferenceObject.h"
|
||||
#include "../eterlib/Ref.h"
|
||||
#include "../eterlib/GrpImageInstance.h"
|
||||
#include "Util.h"
|
||||
|
||||
class CGrannyMaterial : public CReferenceObject
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#include "Mesh.h"
|
||||
#include "Model.h"
|
||||
#include "Material.h"
|
||||
#include "Deform.h"
|
||||
|
||||
granny_data_type_definition GrannyPNT3322VertexType[5] =
|
||||
{
|
||||
@@ -43,45 +42,30 @@ void CGrannyMesh::NEW_LoadVertices(void * dstBaseVertices)
|
||||
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(boneMatrices != NULL);
|
||||
assert(m_pgrnMeshDeformer != NULL);
|
||||
|
||||
const granny_mesh* pgrnMesh = GetGrannyMeshPointer();
|
||||
|
||||
TPNTVertex* srcVertices = (TPNTVertex*)GrannyGetMeshVertices(pgrnMesh);
|
||||
TPNTVertex* dstVertices = ((TPNTVertex*)dstBaseVertices) + m_vtxBasePos;
|
||||
const granny_mesh * pgrnMesh = GetGrannyMeshPointer();
|
||||
|
||||
TPNTVertex * srcVertices = (TPNTVertex *) GrannyGetMeshVertices(pgrnMesh);
|
||||
TPNTVertex * dstVertices = ((TPNTVertex *) dstBaseVertices) + m_vtxBasePos;
|
||||
|
||||
int vtxCount = GrannyGetMeshVertexCount(pgrnMesh);
|
||||
|
||||
// WORK
|
||||
granny_int32x* boneIndices = (granny_int32x*)GrannyGetMeshBindingToBoneIndices(pgrnMeshBinding);
|
||||
granny_int32x * boneIndices = (granny_int32x*)GrannyGetMeshBindingToBoneIndices(pgrnMeshBinding);
|
||||
// END_OF_WORK
|
||||
|
||||
extern bool CPU_HAS_SSE2;
|
||||
if (CPU_HAS_SSE2) {
|
||||
DeformPWNT3432toGrannyPNGBT33332(
|
||||
vtxCount,
|
||||
srcVertices,
|
||||
dstVertices,
|
||||
boneIndices,
|
||||
(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);
|
||||
}
|
||||
GrannyDeformVertices(
|
||||
m_pgrnMeshDeformer,
|
||||
boneIndices,
|
||||
(float *)boneMatrices,
|
||||
vtxCount,
|
||||
srcVertices,
|
||||
dstVertices);
|
||||
}
|
||||
|
||||
bool CGrannyMesh::CanDeformPNTVertices() const
|
||||
|
||||
@@ -109,7 +109,7 @@ bool CGrannyModel::LoadPNTVertices()
|
||||
|
||||
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;
|
||||
|
||||
void* vertices;
|
||||
@@ -257,7 +257,7 @@ BOOL CGrannyModel::CheckMeshIndex(int iIndex) const
|
||||
{
|
||||
if (iIndex < 0)
|
||||
return FALSE;
|
||||
if (iIndex >= GetMeshCount())
|
||||
if (iIndex >= m_meshNodeSize)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
@@ -361,7 +361,7 @@ bool CGrannyModel::__LoadVertices()
|
||||
// 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, m_dwFvF, D3DUSAGE_WRITEONLY, D3DPOOL_DEFAULT))
|
||||
if (!m_pntVtxBuf.Create(m_rigidVtxCount, m_dwFvF, D3DUSAGE_WRITEONLY, D3DPOOL_MANAGED))
|
||||
return false;
|
||||
|
||||
void* vertices;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "Eterlib/GrpVertexBuffer.h"
|
||||
#include "Eterlib/GrpIndexBuffer.h"
|
||||
#include "../eterlib/GrpVertexBuffer.h"
|
||||
#include "../eterlib/GrpIndexBuffer.h"
|
||||
|
||||
#include "Mesh.h"
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "StdAfx.h"
|
||||
#include "ModelInstance.h"
|
||||
#include "Model.h"
|
||||
#include "EterLib/ResourceManager.h"
|
||||
#include "../EterLib/ResourceManager.h"
|
||||
|
||||
|
||||
CGrannyModel* CGrannyModelInstance::GetModel()
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
//#define CACHE_DEFORMED_VERTEX
|
||||
#include "Eterlib/GrpImage.h"
|
||||
#include "Eterlib/GrpCollisionObject.h"
|
||||
#include "../eterlib/GrpImage.h"
|
||||
#include "../eterlib/GrpCollisionObject.h"
|
||||
|
||||
#include "Model.h"
|
||||
#include "Motion.h"
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -232,7 +232,9 @@ void CGrannyModelInstance::__CreateDynamicVertexBuffer()
|
||||
{
|
||||
if (!m_kLocalDeformableVertexBuffer.Create(vtxCount,
|
||||
D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1,
|
||||
D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT
|
||||
//D3DUSAGE_DYNAMIC, D3DPOOL_SYSTEMMEM
|
||||
|
||||
D3DUSAGE_WRITEONLY, D3DPOOL_MANAGED
|
||||
))
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
#include "StdAfx.h"
|
||||
#include "Eterlib/StateManager.h"
|
||||
#include "../eterlib/StateManager.h"
|
||||
#include "ModelInstance.h"
|
||||
#include "Model.h"
|
||||
|
||||
#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)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "StdAfx.h"
|
||||
#include "Eterbase/Debug.h"
|
||||
#include "../eterbase/Debug.h"
|
||||
#include "ModelInstance.h"
|
||||
#include "Model.h"
|
||||
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
//#include <crtdbg.h>
|
||||
#include <granny.h>
|
||||
|
||||
#include "EterBase/Utils.h"
|
||||
#include "EterBase/Debug.h"
|
||||
#include "EterBase/Stl.h"
|
||||
#include "../eterBase/Utils.h"
|
||||
#include "../eterBase/Debug.h"
|
||||
#include "../eterBase/Stl.h"
|
||||
|
||||
#include "Util.h"
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "StdAfx.h"
|
||||
#include "Eterbase/Debug.h"
|
||||
#include "../eterbase/Debug.h"
|
||||
#include "Thing.h"
|
||||
#include "ThingInstance.h"
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "StdAfx.h"
|
||||
#include "Eterbase/Debug.h"
|
||||
#include "Eterlib/Camera.h"
|
||||
#include "EterBase/Timer.h"
|
||||
#include "../eterbase/Debug.h"
|
||||
#include "../eterlib/Camera.h"
|
||||
#include "../eterBase/Timer.h"
|
||||
#include "ThingInstance.h"
|
||||
#include "Thing.h"
|
||||
#include "ModelInstance.h"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "Eterbase/Stl.h"
|
||||
#include "Eterlib/GrpObjectInstance.h"
|
||||
#include "Eterlib/GrpShadowTexture.h"
|
||||
#include "../eterbase/Stl.h"
|
||||
#include "../eterlib/GrpObjectInstance.h"
|
||||
#include "../eterlib/GrpShadowTexture.h"
|
||||
|
||||
#include "LODController.h"
|
||||
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
add_library(EterImageLib STATIC ${FILE_SOURCES})
|
||||
|
||||
target_link_libraries(EterImageLib
|
||||
cryptopp-static
|
||||
mio
|
||||
lzo2
|
||||
)
|
||||
|
||||
GroupSourcesByFolder(EterImageLib)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
Reference in New Issue
Block a user