scripting and a bunch of rendering fixes

This commit is contained in:
sshumakov3
2021-09-02 02:07:56 +03:00
parent c22a76e55a
commit 9d960b2422
88 changed files with 9210 additions and 125 deletions

View File

@@ -322,6 +322,7 @@ include_directories(${Qt5Gui_PRIVATE_INCLUDE_DIRS})
collect_files(noggit_root_sources src/noggit false "*.cpp" "")
collect_files(noggit_ui_sources src/noggit/ui true "*.cpp" "")
collect_files(noggit_scripting_sources src/noggit/scripting true "*.cpp" "")
collect_files(math_sources src/math false "*.cpp" "")
collect_files(opengl_sources src/opengl false "*.cpp" "")
@@ -343,6 +344,7 @@ set ( util_sources
collect_files(noggit_root_headers src/noggit false "*.h;*.hpp;*.inl" "")
collect_files(noggit_ui_headers src/noggit/ui true "*.h;*.hpp" "")
collect_files(noggit_scripting_headers src/noggit/scripting true "*.h;*.hpp" "")
collect_files(math_headers src/math false "*.h;*.hpp" "")
collect_files(opengl_headers src/opengl false "*.h;*.hpp" "")
collect_files(shaders src/glsl false "*.glsl" "")
@@ -374,6 +376,7 @@ ENDIF(WIN32)
#qt5_wrap_cpp (moced ${result})
source_group("noggit" FILES ${noggit_root_sources} ${noggit_root_headers})
source_group("noggit\\ui" FILES ${noggit_ui_sources} ${noggit_ui_headers})
source_group("noggit\\scripting" FILES ${noggit_scripting_sources} ${noggit_scripting_headers})
source_group("opengl" FILES ${opengl_sources} ${opengl_headers})
source_group("math" FILES ${math_sources} ${math_headers})
source_group("external" FILES ${external_sources} ${external_headers})
@@ -395,6 +398,7 @@ ADD_EXECUTABLE ( noggit
MACOSX_BUNDLE
${noggit_root_sources}
${noggit_ui_sources}
${noggit_scripting_sources}
${opengl_sources}
${math_sources}
${external_sources}
@@ -409,6 +413,7 @@ ADD_EXECUTABLE ( noggit
${tracy_sources}
${noggit_root_headers}
${noggit_ui_headers}
${noggit_scripting_headers}
${opengl_headers}
${math_headers}
${external_headers}
@@ -531,3 +536,79 @@ add_executable (math-matrix_4x4.test test/math/matrix_4x4.cpp)
target_compile_definitions (math-matrix_4x4.test PRIVATE "-DBOOST_TEST_MODULE=\"math\"")
target_link_libraries (math-matrix_4x4.test Boost::unit_test_framework noggit::math)
add_test (NAME math-matrix_4x4 COMMAND $<TARGET_FILE:math-matrix_4x4.test>)
include (FetchContent)
# Dependency: json.hpp
FetchContent_Declare (json
GIT_REPOSITORY https://github.com/ArthurSonzogni/nlohmann_json_cmake_fetchcontent
GIT_TAG v3.9.1
)
FetchContent_GetProperties (json)
if (NOT json_POPULATED)
message (STATUS "Installing json.hpp...")
FetchContent_Populate (json)
endif()
add_subdirectory (${json_SOURCE_DIR} ${json_BINARY_DIR} EXCLUDE_FROM_ALL)
# Dependency: lodepng
FetchContent_Declare (lodepng
GIT_REPOSITORY https://github.com/lvandeve/lodepng.git
GIT_TAG 7fdcc96a5e5864eee72911c3ca79b1d9f0d12292
)
FetchContent_GetProperties (lodepng)
if (NOT lodepng_POPULATED)
message (STATUS "Installing lodepng...")
FetchContent_Populate (lodepng)
endif()
add_library (lodepng "${lodepng_SOURCE_DIR}/lodepng.cpp")
target_include_directories (lodepng SYSTEM PUBLIC ${lodepng_SOURCE_DIR})
# Dependency: FastNoise2
FetchContent_Declare (fastnoise2
GIT_REPOSITORY https://github.com/tswow/FastNoise2.git
GIT_TAG v0.0.1-heightmap
PATCH_COMMAND "${CMAKE_COMMAND}" -P "${CMAKE_SOURCE_DIR}/cmake/deps/patch_fastnoise2.cmake"
UPDATE_DISCONNECTED true
)
FetchContent_GetProperties (fastnoise2)
if (NOT fastnoise2_POPULATED)
message (STATUS "Installing FastNoise2... (big repo, large download)")
FetchContent_Populate (fastnoise2)
endif()
set(FASTNOISE2_NOISETOOL OFF)
set(FASTNOISE2_TESTS:BOOL OFF)
if (FASTNOISE2_NOISETOOL)
add_subdirectory (${fastnoise2_SOURCE_DIR} ${fastnoise2_BINARY_DIR})
else()
add_subdirectory (${fastnoise2_SOURCE_DIR} ${fastnoise2_BINARY_DIR} EXCLUDE_FROM_ALL)
endif()
# Dependency: Lua
find_package (Lua REQUIRED)
add_library (Lua-Lua INTERFACE)
add_library (Lua::Lua ALIAS Lua-Lua)
target_link_libraries (Lua-Lua INTERFACE ${LUA_LIBRARIES})
target_include_directories (Lua-Lua INTERFACE ${LUA_INCLUDE_DIR})
# Dependency: sol2
FetchContent_Declare (sol2
GIT_REPOSITORY https://github.com/tswow/sol2
GIT_TAG b9c83d5ecf6bc9503dc66779f2395dc32dffb1e5
)
FetchContent_MakeAvailable (sol2)
# sol2::sol2 neither links lua nor sets include directories as system so will clobber us with
# loads of warnings, sadly. It also wants to be install(EXPORT)ed which is not what we want.
add_library (sane-sol2 INTERFACE)
add_library (sol2::sane ALIAS sane-sol2)
target_link_libraries (sane-sol2 INTERFACE Lua::Lua)
target_include_directories (sane-sol2 SYSTEM INTERFACE "${sol2_SOURCE_DIR}/include")
target_link_libraries (noggit
lodepng
FastNoise
nlohmann_json::nlohmann_json
sol2::sane
)

View File

@@ -0,0 +1,4 @@
# please don't spam root source directory with test things
file (READ "CMakeLists.txt" cmakelists_content)
string (REPLACE "UNITIZE_BUILD(\"examples/test/unit_tests\" TEST_GENERATED_SRC)" "# noggit patch: examples removed" cmakelists_content "${cmakelists_content}")
file (WRITE "CMakeLists.txt" "${cmakelists_content}")

View File

@@ -0,0 +1,7 @@
# set includes etc relative to fastnoise2 root directory, not noggit's
file (GLOB_RECURSE cmakelists LIST_DIRECTORIES FALSE "CMakeLists.txt")
foreach (cmakelist ${cmakelists})
file (READ "${cmakelist}" cmakelists_content)
string (REPLACE "CMAKE_SOURCE_DIR" "PROJECT_SOURCE_DIR" cmakelists_content "${cmakelists_content}")
file (WRITE "${cmakelist}" "${cmakelists_content}")
endforeach()

42
scripts/clean.lua Normal file
View File

@@ -0,0 +1,42 @@
-- This file is part of Noggit3, licensed under GNU General Public License (version 3).
local clean = brush("Clean");
local def_height = clean:add_real_tag("Default height",-1000,1000,0)
local tex_layer_1 = clean:add_string_tag("Texture layer 1","")
local prop_layer_1 = clean:add_int_tag("Effect layer 1",-2,9999999999,-2)
local tex_layer_2 = clean:add_string_tag("Texture layer 2","")
local prop_layer_2 = clean:add_int_tag("Effect layer 2",-2,9999999999,-2)
local tex_layer_3 = clean:add_string_tag("Texture layer 3","")
local prop_layer_3 = clean:add_int_tag("Effect layer 3",-2,9999999999,-2)
local tex_layer_4 = clean:add_string_tag("Texture layer 4","")
local prop_layer_4 = clean:add_int_tag("Effect layer 4",-2,9999999999,-2)
function clean:on_left_hold(evt)
local sel = select_origin(evt:pos(), evt:outer_radius(), evt:outer_radius())
if(holding_shift()) then
for i,chunk in pairs(sel:chunks()) do
chunk:clear_textures()
chunk:clear_colors()
if tex_layer_1:get() ~= "" then chunk:add_texture(tex_layer_1:get(),prop_layer_1:get()) end
if tex_layer_2:get() ~= "" then chunk:add_texture(tex_layer_2:get(),prop_layer_2:get()) end
if tex_layer_3:get() ~= "" then chunk:add_texture(tex_layer_3:get(),prop_layer_3:get()) end
if tex_layer_4:get() ~= "" then chunk:add_texture(tex_layer_4:get(),prop_layer_4:get()) end
chunk:apply_all()
end
end
if(holding_ctrl()) then
for i,vert in pairs(sel:verts()) do
vert:set_height(def_height:get())
end
end
if(holding_alt()) then
for i,model in pairs(sel:models()) do
model:remove()
end
end
sel:apply()
end

101
scripts/docs/README.md Normal file
View File

@@ -0,0 +1,101 @@
# Scripting
[API Documentation](api/modules.md)
This version of Noggit has support for scriptable brushes, meaning you can use the Lua programming language (version 5.1) to customize your own workflow.
Script brushes should be placed in the `scripts` subdirectory in your Noggit installation. Script brushes can be loaded inside Noggit from the scripting tool (book icon) in the menu to the left.
**Warning**: Scripts are created by third party developers and are not maintained by Noggit. Scripts downloaded from the internet might contain malicious code.
## Hello World
This example illustrates a simple working script brush that you can load in the scripting tool.
```lua
-- We create a new script brush that becomes
local my_brush = brush("My Brush")
-- We register an event for when this brush clicks on the ground
function my_brush:on_left_click(evt)
print("Hello world!")
end
```
## Script Parameters
Script brushes can register custom settings that the user can configure without editing the script.
```lua
local parameter_brush = brush("Parameter Brush")
-- Editable string
local string_param = parameter_brush:add_string_tag("Parameter Name","default value")
-- Integer between 1 and 50, default value of 5
local int_param = parameter_brush:add_int_tag("Int Tag",1,50,5)
-- Real between 0.0005 and 1, default value of 0.001 and at most 5 decimal points.
local real_param = parameter_brush:add_real_tag("Real Tag",0.0005,1.0,0.001,5)
-- Checkbox
local bool_param = parameter_brush:add_bool_tag("Bool Tag",false)
function parameter_brush:on_left_click(evt)
-- We can now access the tag values from the brush event
print("String: " .. string_param:get())
print("Bool: " .. bool_param:get())
print("Int: " .. int_param:get())
print("Real: " .. real_param:get())
-- And we can access the special radius settings from the event parameter
print("Outer brush radius:" .. evt:outer_radius())
print("Inner brush radius" .. evt:inner_radius())
end
```
## Selections
Most noggit operations involve some kind of selection using the Noggit API.
The following code illustrates how we can iterate various data in Noggit:
```lua
local selection_brush = brush("Selection Brush")
function selection_brush:on_left_click(evt)
-- Creates a square selection at the clicked position
-- containing the entire outer brush circle
local sel = select_origin(evt:pos(), evt:outer_radius())
-- iterate selected chunks
for i,chunk in pairs(sel:chunks()) do
-- do something to the chunk here
end
-- iterate selected vertices
for i,vert in pairs(sel:verts()) do
-- do something to the vertex here
end
-- iterate selected texture units
for i,tex in pairs(sel:tex()) do
-- do something to the texture unit here
end
-- iterate selected models (m2 and wmo)
for i,model in pairs(sel:model()) do
-- do something to the model here
end
end
```
## Noggit API
To see all the predefined functions you can call from scripts, see the [API documentation](api/modules.md).
### File System Permissions
The functions [image::save](api/classes/image####save) and [write_file](api/modules.md####write_file) can be used to write to the users file systems. By default, when a script tries to call either of these functions the user will be prompted with a popup to confirm they wish to write to that file. If they answer no, an exception will be thrown and stop execution of the script, and if they answer yes the file will be written, and can be written to again without asking until Noggit is restarted.
This default behavior can be disabled in the Noggit settings under `Allow scripts to write to any file`.

View File

@@ -0,0 +1,309 @@
# Class: chunk
Represents a chunk in the world
## Table of contents
### Constructors
- [constructor](chunk.md#constructor)
### Methods
- [add\_texture](chunk.md#add_texture)
- [apply](chunk.md#apply)
- [apply\_all](chunk.md#apply_all)
- [apply\_heightmap](chunk.md#apply_heightmap)
- [apply\_textures](chunk.md#apply_textures)
- [apply\_vertex\_color](chunk.md#apply_vertex_color)
- [clear\_colors](chunk.md#clear_colors)
- [clear\_textures](chunk.md#clear_textures)
- [get\_area\_id](chunk.md#get_area_id)
- [get\_effect](chunk.md#get_effect)
- [get\_tex](chunk.md#get_tex)
- [get\_texture](chunk.md#get_texture)
- [get\_texture\_count](chunk.md#get_texture_count)
- [get\_vert](chunk.md#get_vert)
- [remove\_texture](chunk.md#remove_texture)
- [set\_area\_id](chunk.md#set_area_id)
- [set\_effect](chunk.md#set_effect)
- [set\_hole](chunk.md#set_hole)
- [set\_impassable](chunk.md#set_impassable)
- [to\_selection](chunk.md#to_selection)
## Constructors
### constructor
\+ **new chunk**(): [*chunk*](chunk.md)
**Returns:** [*chunk*](chunk.md)
## Methods
### add\_texture
**add_texture**(`texture`: *string*, `effect`: *number*): *number*
Adds a new texture at the current topmost layer.
**`note`** A chunk can hold at most 4 texture layers.
#### Parameters:
Name | Type | Description |
:------ | :------ | :------ |
`texture` | *string* | |
`effect` | *number* | effect id to add - -2 (default): does not change effect - -1: clears current effect index - 0+: change to this effect index |
**Returns:** *number*
texture index added to
___
### apply
**apply**(): *void*
Same as apply_all
**Returns:** *void*
___
### apply\_all
**apply_all**(): *void*
Applies all changes in this chunk
**Returns:** *void*
___
### apply\_heightmap
**apply_heightmap**(): *void*
Applies all changes to the heightmap in this chunk
**Returns:** *void*
___
### apply\_textures
**apply_textures**(): *void*
Applies all changes to texture alphamaps in this chunk
**Returns:** *void*
___
### apply\_vertex\_color
**apply_vertex_color**(): *void*
Applies all changes to vertex colors in this chunk
**Returns:** *void*
___
### clear\_colors
**clear_colors**(): *void*
Removes all vertex colors in this chunk
**Returns:** *void*
___
### clear\_textures
**clear_textures**(): *void*
Removes all texture layers in this chunk
**Returns:** *void*
___
### get\_area\_id
**get_area_id**(): *number*
Returns the area id of a chunk
**Returns:** *number*
___
### get\_effect
**get_effect**(`layer`: *number*): *number*
Returns the effect id at a texture layer
#### Parameters:
Name | Type |
:------ | :------ |
`layer` | *number* |
**Returns:** *number*
___
### get\_tex
**get_tex**(`index`: *number*): [*tex*](tex.md)
Returns a texel by index in this chunk
#### Parameters:
Name | Type | Description |
:------ | :------ | :------ |
`index` | *number* | valid in range [0-4095] |
**Returns:** [*tex*](tex.md)
___
### get\_texture
**get_texture**(`index`: *number*): *string*
Returns the name of the texture at the specified layer.
#### Parameters:
Name | Type |
:------ | :------ |
`index` | *number* |
**Returns:** *string*
___
### get\_texture\_count
**get_texture_count**(): *number*
Returns the amount of textures on this chunk
**Returns:** *number*
___
### get\_vert
**get_vert**(`index`: *number*): [*vert*](vert.md)
Returns a vertex by index in this chunk
#### Parameters:
Name | Type | Description |
:------ | :------ | :------ |
`index` | *number* | valid in range [0-144] |
**Returns:** [*vert*](vert.md)
___
### remove\_texture
**remove_texture**(`index`: *number*): *void*
Removes a texture layer from this chunk
and decreases the texture ids of all higher layers by 1
#### Parameters:
Name | Type |
:------ | :------ |
`index` | *number* |
**Returns:** *void*
___
### set\_area\_id
**set_area_id**(`value`: *number*): *void*
Changes the area id of a chunk
#### Parameters:
Name | Type |
:------ | :------ |
`value` | *number* |
**Returns:** *void*
___
### set\_effect
**set_effect**(`layer`: *number*, `effect`: *number*): *any*
Changes the effect id at a texture layer
#### Parameters:
Name | Type | Description |
:------ | :------ | :------ |
`layer` | *number* | |
`effect` | *number* | effect id to set (-1 to remove effects) |
**Returns:** *any*
___
### set\_hole
**set_hole**(`hole`: *boolean*): *void*
Creates or removes a hole in this chunk
#### Parameters:
Name | Type |
:------ | :------ |
`hole` | *boolean* |
**Returns:** *void*
___
### set\_impassable
**set_impassable**(`impassable`: *boolean*): *void*
Sets whether this chunk should be impassable for players or not
#### Parameters:
Name | Type |
:------ | :------ |
`impassable` | *boolean* |
**Returns:** *void*
___
### to\_selection
**to_selection**(): [*selection*](selection.md)
Returns a selection spanning this chunk
**`note`** - iterating will include border vert/texels
**Returns:** [*selection*](selection.md)

View File

@@ -0,0 +1,209 @@
# Class: image
Represents a bitmap image
images can be created from create_image or load_png
## Table of contents
### Constructors
- [constructor](image.md#constructor)
### Methods
- [get\_alpha](image.md#get_alpha)
- [get\_blue](image.md#get_blue)
- [get\_green](image.md#get_green)
- [get\_pixel](image.md#get_pixel)
- [get\_red](image.md#get_red)
- [gradient\_scale](image.md#gradient_scale)
- [height](image.md#height)
- [save](image.md#save)
- [set\_pixel](image.md#set_pixel)
- [set\_pixel\_floats](image.md#set_pixel_floats)
- [width](image.md#width)
## Constructors
### constructor
\+ **new image**(): [*image*](image.md)
**Returns:** [*image*](image.md)
## Methods
### get\_alpha
**get_alpha**(`x`: *number*, `y`: *number*): *number*
Returns the alpha channel (between 0-1) at an image coordinate
#### Parameters:
Name | Type |
:------ | :------ |
`x` | *number* |
`y` | *number* |
**Returns:** *number*
___
### get\_blue
**get_blue**(`x`: *number*, `y`: *number*): *number*
Returns the blue channel (between 0-1) at an image coordinate
#### Parameters:
Name | Type |
:------ | :------ |
`x` | *number* |
`y` | *number* |
**Returns:** *number*
___
### get\_green
**get_green**(`x`: *number*, `y`: *number*): *number*
Returns the green channel (between 0-1) at an image coordinate
#### Parameters:
Name | Type |
:------ | :------ |
`x` | *number* |
`y` | *number* |
**Returns:** *number*
___
### get\_pixel
**get_pixel**(`x`: *number*, `y`: *number*): *number*
Returns the pixel value at a coordinate
#### Parameters:
Name | Type |
:------ | :------ |
`x` | *number* |
`y` | *number* |
**Returns:** *number*
___
### get\_red
**get_red**(`x`: *number*, `y`: *number*): *number*
Returns the red channel (between 0-1) at an image coordinate
#### Parameters:
Name | Type |
:------ | :------ |
`x` | *number* |
`y` | *number* |
**Returns:** *number*
___
### gradient\_scale
**gradient_scale**(`rel`: *number*): *number*
Returns the pixel value at a relative horizontal coordinate
#### Parameters:
Name | Type | Description |
:------ | :------ | :------ |
`rel` | *number* | horizontal relative position (between 0-1) |
**Returns:** *number*
___
### height
**height**(): *number*
Returns the height of this image
**Returns:** *number*
___
### save
**save**(`filename`: *string*): *any*
Saves this image to a file
#### Parameters:
Name | Type |
:------ | :------ |
`filename` | *string* |
**Returns:** *any*
___
### set\_pixel
**set_pixel**(`x`: *number*, `y`: *number*, `value`: *number*): *void*
Sets the pixel value at an image coordinate
#### Parameters:
Name | Type |
:------ | :------ |
`x` | *number* |
`y` | *number* |
`value` | *number* |
**Returns:** *void*
___
### set\_pixel\_floats
**set_pixel_floats**(`x`: *number*, `y`: *number*, `r`: *number*, `g`: *number*, `b`: *number*, `a`: *number*): *void*
Sets the pixel value at an image coordinate
#### Parameters:
Name | Type | Description |
:------ | :------ | :------ |
`x` | *number* | |
`y` | *number* | |
`r` | *number* | should be between 0-1 |
`g` | *number* | should be between 0-1 |
`b` | *number* | should be between 0-1 |
`a` | *number* | should be between 0-1 |
**Returns:** *void*
___
### width
**width**(): *number*
Returns the width of this image
**Returns:** *number*

View File

@@ -0,0 +1,149 @@
# Class: model
Represents a model in the world. Can represent both an m2 and wmo model.
## Table of contents
### Constructors
- [constructor](model.md#constructor)
### Methods
- [get\_filename](model.md#get_filename)
- [get\_pos](model.md#get_pos)
- [get\_rot](model.md#get_rot)
- [get\_scale](model.md#get_scale)
- [get\_uid](model.md#get_uid)
- [has\_filename](model.md#has_filename)
- [remove](model.md#remove)
- [replace](model.md#replace)
- [set\_pos](model.md#set_pos)
- [set\_rot](model.md#set_rot)
- [set\_scale](model.md#set_scale)
## Constructors
### constructor
\+ **new model**(): [*model*](model.md)
**Returns:** [*model*](model.md)
## Methods
### get\_filename
**get_filename**(): *string*
**Returns:** *string*
___
### get\_pos
**get_pos**(): [*vector\_3d*](vector_3d.md)
**Returns:** [*vector\_3d*](vector_3d.md)
___
### get\_rot
**get_rot**(): [*vector\_3d*](vector_3d.md)
**Returns:** [*vector\_3d*](vector_3d.md)
___
### get\_scale
**get_scale**(): *number*
**Returns:** *number*
___
### get\_uid
**get_uid**(): *number*
**Returns:** *number*
___
### has\_filename
**has_filename**(`name`: *string*): *boolean*
#### Parameters:
Name | Type |
:------ | :------ |
`name` | *string* |
**Returns:** *boolean*
___
### remove
**remove**(): *void*
**Returns:** *void*
___
### replace
**replace**(`filename`: *string*): *any*
#### Parameters:
Name | Type |
:------ | :------ |
`filename` | *string* |
**Returns:** *any*
___
### set\_pos
**set_pos**(`pos`: [*vector\_3d*](vector_3d.md)): *void*
#### Parameters:
Name | Type |
:------ | :------ |
`pos` | [*vector\_3d*](vector_3d.md) |
**Returns:** *void*
___
### set\_rot
**set_rot**(`pos`: [*vector\_3d*](vector_3d.md)): *void*
#### Parameters:
Name | Type |
:------ | :------ |
`pos` | [*vector\_3d*](vector_3d.md) |
**Returns:** *void*
___
### set\_scale
**set_scale**(`scale`: *number*): *void*
#### Parameters:
Name | Type |
:------ | :------ |
`scale` | *number* |
**Returns:** *void*

View File

@@ -0,0 +1,96 @@
# Class: noisemap
Represents a map of floats values, typically use with a
noise generator.
## Table of contents
### Constructors
- [constructor](noisemap.md#constructor)
### Methods
- [get](noisemap.md#get)
- [height](noisemap.md#height)
- [is\_highest](noisemap.md#is_highest)
- [set](noisemap.md#set)
- [width](noisemap.md#width)
## Constructors
### constructor
\+ **new noisemap**(): [*noisemap*](noisemap.md)
**Returns:** [*noisemap*](noisemap.md)
## Methods
### get
**get**(`pos`: [*vector\_3d*](vector_3d.md)): *number*
Returns the float value at a specific 3d position.
**`note`** The 'y' value of pos is ignored by this operation.
#### Parameters:
Name | Type |
:------ | :------ |
`pos` | [*vector\_3d*](vector_3d.md) |
**Returns:** *number*
___
### height
**height**(): *number*
**Returns:** *number*
___
### is\_highest
**is_highest**(`pos`: [*vector\_3d*](vector_3d.md), `check_radius`: *number*): *boolean*
Returns true if the float value at a 3d position
is the highest position within a given range.
This is typically used for object placement.
#### Parameters:
Name | Type |
:------ | :------ |
`pos` | [*vector\_3d*](vector_3d.md) |
`check_radius` | *number* |
**Returns:** *boolean*
___
### set
**set**(`x`: *number*, `y`: *number*, `value`: *number*): *void*
#### Parameters:
Name | Type |
:------ | :------ |
`x` | *number* |
`y` | *number* |
`value` | *number* |
**Returns:** *void*
___
### width
**width**(): *number*
**Returns:** *number*

View File

@@ -0,0 +1,41 @@
# Class: procedures\_class
Contains some general-purpose procedures that don't fit anywhere else.
Access these functions through the global singleton "procedures".
## Table of contents
### Constructors
- [constructor](procedures_class.md#constructor)
### Methods
- [paint\_texture](procedures_class.md#paint_texture)
## Constructors
### constructor
\+ **new procedures_class**(): [*procedures\_class*](procedures_class.md)
**Returns:** [*procedures\_class*](procedures_class.md)
## Methods
### paint\_texture
**paint_texture**(`sel`: [*selection*](selection.md), `img`: [*image*](image.md), `layer`: *number*, `pressure`: *number*, `angle`: *number*): *any*
#### Parameters:
Name | Type |
:------ | :------ |
`sel` | [*selection*](selection.md) |
`img` | [*image*](image.md) |
`layer` | *number* |
`pressure` | *number* |
`angle` | *number* |
**Returns:** *any*

View File

@@ -0,0 +1,52 @@
# Class: random
Represents a random generator and its state.
## Table of contents
### Constructors
- [constructor](random.md#constructor)
### Methods
- [integer](random.md#integer)
- [real](random.md#real)
## Constructors
### constructor
\+ **new random**(): [*random*](random.md)
**Returns:** [*random*](random.md)
## Methods
### integer
**integer**(`low`: *number*, `high`: *number*): *number*
#### Parameters:
Name | Type |
:------ | :------ |
`low` | *number* |
`high` | *number* |
**Returns:** *number*
___
### real
**real**(`low`: *number*, `high`: *number*): *number*
#### Parameters:
Name | Type |
:------ | :------ |
`low` | *number* |
`high` | *number* |
**Returns:** *number*

View File

@@ -0,0 +1,233 @@
# Class: script\_brush
Represents a script brush in the script window.
## Table of contents
### Constructors
- [constructor](script_brush.md#constructor)
### Properties
- [on\_left\_click](script_brush.md#on_left_click)
- [on\_left\_hold](script_brush.md#on_left_hold)
- [on\_left\_release](script_brush.md#on_left_release)
- [on\_right\_click](script_brush.md#on_right_click)
- [on\_right\_hold](script_brush.md#on_right_hold)
- [on\_right\_release](script_brush.md#on_right_release)
### Methods
- [add\_bool\_tag](script_brush.md#add_bool_tag)
- [add\_description](script_brush.md#add_description)
- [add\_int\_tag](script_brush.md#add_int_tag)
- [add\_null\_tag](script_brush.md#add_null_tag)
- [add\_real\_tag](script_brush.md#add_real_tag)
- [add\_string\_list\_tag](script_brush.md#add_string_list_tag)
- [add\_string\_tag](script_brush.md#add_string_tag)
- [get\_name](script_brush.md#get_name)
- [set\_name](script_brush.md#set_name)
## Constructors
### constructor
\+ **new script_brush**(): [*script\_brush*](script_brush.md)
**Returns:** [*script\_brush*](script_brush.md)
## Properties
### on\_left\_click
**on\_left\_click**: [*callback*](../modules.md#callback)<(`brush`: [*script\_brush*](script_brush.md), `event`: [*script\_brush\_event*](script_brush_event.md)) => *void*\>
The function to call when the user left clicks
the world with this brush
___
### on\_left\_hold
**on\_left\_hold**: [*callback*](../modules.md#callback)<(`brush`: [*script\_brush*](script_brush.md), `event`: [*script\_brush\_event*](script_brush_event.md)) => *void*\>
The funciton to call when the user holds the left mouse button
in the world with this brush
___
### on\_left\_release
**on\_left\_release**: [*callback*](../modules.md#callback)<(`brush`: [*script\_brush*](script_brush.md), `event`: [*script\_brush\_event*](script_brush_event.md)) => *void*\>
The function to call when the user releases the left moues button
in the world with this brush
___
### on\_right\_click
**on\_right\_click**: [*callback*](../modules.md#callback)<(`brush`: [*script\_brush*](script_brush.md), `event`: [*script\_brush\_event*](script_brush_event.md)) => *void*\>
The function to call when the user right clicks
the world with this brush
___
### on\_right\_hold
**on\_right\_hold**: [*callback*](../modules.md#callback)<(`brush`: [*script\_brush*](script_brush.md), `event`: [*script\_brush\_event*](script_brush_event.md)) => *void*\>
The funciton to call when the user holds the right mouse button
in the world with this brush
___
### on\_right\_release
**on\_right\_release**: [*callback*](../modules.md#callback)<(`brush`: [*script\_brush*](script_brush.md), `event`: [*script\_brush\_event*](script_brush_event.md)) => *void*\>
The function to call when the user releases the right mouse button
in the world with this brush
## Methods
### add\_bool\_tag
**add_bool_tag**(`item`: *string*, `def`: *boolean*): [*tag*](tag.md)<boolean\>
Adds a bool tag to the settings panel
#### Parameters:
Name | Type |
:------ | :------ |
`item` | *string* |
`def` | *boolean* |
**Returns:** [*tag*](tag.md)<boolean\>
___
### add\_description
**add_description**(`text`: *string*): *any*
Adds a description row to the brush window
#### Parameters:
Name | Type |
:------ | :------ |
`text` | *string* |
**Returns:** *any*
___
### add\_int\_tag
**add_int_tag**(`item`: *string*, `low`: *number*, `high`: *number*, `def`: *number*): [*tag*](tag.md)<number\>
Adds an integer tag to the settings panel
#### Parameters:
Name | Type |
:------ | :------ |
`item` | *string* |
`low` | *number* |
`high` | *number* |
`def` | *number* |
**Returns:** [*tag*](tag.md)<number\>
___
### add\_null\_tag
**add_null_tag**(): *any*
Adds an empty tag, typically used to create empty lines in the settings panel
**Returns:** *any*
___
### add\_real\_tag
**add_real_tag**(`item`: *string*, `low`: *number*, `high`: *number*, `def`: *number*): [*tag*](tag.md)<number\>
Adds a real (i.e. float) tag to the settings panel
#### Parameters:
Name | Type |
:------ | :------ |
`item` | *string* |
`low` | *number* |
`high` | *number* |
`def` | *number* |
**Returns:** [*tag*](tag.md)<number\>
___
### add\_string\_list\_tag
**add_string_list_tag**(`item`: *string*, ...`values`: *string*[]): [*tag*](tag.md)<string\>
Adds a dropdown menu to the settings panel
#### Parameters:
Name | Type |
:------ | :------ |
`item` | *string* |
`...values` | *string*[] |
**Returns:** [*tag*](tag.md)<string\>
___
### add\_string\_tag
**add_string_tag**(`item`: *string*, `def`: *string*): [*tag*](tag.md)<string\>
Adds a string tag to the settings panel
#### Parameters:
Name | Type |
:------ | :------ |
`item` | *string* |
`def` | *string* |
**Returns:** [*tag*](tag.md)<string\>
___
### get\_name
**get_name**(): *string*
Returns the current name of this script brush
**Returns:** *string*
___
### set\_name
**set_name**(`name`: *string*): *void*
Changes the name of this script brush
#### Parameters:
Name | Type |
:------ | :------ |
`name` | *string* |
**Returns:** *void*

View File

@@ -0,0 +1,99 @@
# Class: script\_brush\_event
Represents the event context passed to brush click events.
## Table of contents
### Constructors
- [constructor](script_brush_event.md#constructor)
### Methods
- [dt](script_brush_event.md#dt)
- [inner\_radius](script_brush_event.md#inner_radius)
- [outer\_radius](script_brush_event.md#outer_radius)
- [pos](script_brush_event.md#pos)
- [set\_inner\_radius](script_brush_event.md#set_inner_radius)
- [set\_outer\_radius](script_brush_event.md#set_outer_radius)
## Constructors
### constructor
\+ **new script_brush_event**(): [*script\_brush\_event*](script_brush_event.md)
**Returns:** [*script\_brush\_event*](script_brush_event.md)
## Methods
### dt
**dt**(): *number*
Returns the delta-time since the last update frame
**Returns:** *number*
___
### inner\_radius
**inner_radius**(): *number*
Returns the current inner radius configured in the settings panel
**Returns:** *number*
___
### outer\_radius
**outer_radius**(): *number*
Returns the current outer radius configured in the settings panel
**Returns:** *number*
___
### pos
**pos**(): [*vector\_3d*](vector_3d.md)
Returns world position of this click event.
i.e. the world position where the user clicked, held or released a mouse button
**Returns:** [*vector\_3d*](vector_3d.md)
___
### set\_inner\_radius
**set_inner_radius**(`value`: *number*): *any*
Sets the outer radius in the settings panel for this brush
#### Parameters:
Name | Type | Description |
:------ | :------ | :------ |
`value` | *number* | should be between 0-1 |
**Returns:** *any*
___
### set\_outer\_radius
**set_outer_radius**(`value`: *number*): *any*
Sets the outer radius in the settings panel for this brush
#### Parameters:
Name | Type |
:------ | :------ |
`value` | *number* |
**Returns:** *any*

View File

@@ -0,0 +1,143 @@
# Class: selection
Represents a rectangular selection in the world and provides
iterators for heightmap vertices, texture units, chunks and models within it.
## Table of contents
### Constructors
- [constructor](selection.md#constructor)
### Methods
- [apply](selection.md#apply)
- [center](selection.md#center)
- [chunks](selection.md#chunks)
- [make\_noise](selection.md#make_noise)
- [max](selection.md#max)
- [min](selection.md#min)
- [models](selection.md#models)
- [size](selection.md#size)
- [tex](selection.md#tex)
- [verts](selection.md#verts)
## Constructors
### constructor
\+ **new selection**(): [*selection*](selection.md)
**Returns:** [*selection*](selection.md)
## Methods
### apply
**apply**(): *void*
Applies all changes made inside this selection.
You almost always want to call this function when you're done
with a selection.
**Returns:** *void*
___
### center
**center**(): [*vector\_3d*](vector_3d.md)
Returns the center point of this selection
**Returns:** [*vector\_3d*](vector_3d.md)
___
### chunks
**chunks**(): [*chunk*](chunk.md)[]
Creates and returns an iterator for all chunks inside this selection
**Returns:** [*chunk*](chunk.md)[]
___
### make\_noise
**make_noise**(`frequency`: *number*, `algorithm`: *string*, `seed`: *string*): [*noisemap*](noisemap.md)
Creates a noisemap matching the location of this selection
#### Parameters:
Name | Type |
:------ | :------ |
`frequency` | *number* |
`algorithm` | *string* |
`seed` | *string* |
**Returns:** [*noisemap*](noisemap.md)
___
### max
**max**(): [*vector\_3d*](vector_3d.md)
Returns the highest point of this selection
**Returns:** [*vector\_3d*](vector_3d.md)
___
### min
**min**(): [*vector\_3d*](vector_3d.md)
Returns the smallest point of this selection
**Returns:** [*vector\_3d*](vector_3d.md)
___
### models
**models**(): [*model*](model.md)[]
Creates and returns an iterator for all models inside this selection
**Returns:** [*model*](model.md)[]
___
### size
**size**(): [*vector\_3d*](vector_3d.md)
Returns a vector representing the size of this selection on each axis.
**`note`** for iterators, only x and z values are respected. y (height) is ignored.
**Returns:** [*vector\_3d*](vector_3d.md)
___
### tex
**tex**(): [*tex*](tex.md)[]
Creates and returns an iterator for all texture units inside this selection
**Returns:** [*tex*](tex.md)[]
___
### verts
**verts**(): [*vert*](vert.md)[]
Creates and returns an iterator for all vertices inside this selection
**Returns:** [*vert*](vert.md)[]

View File

@@ -0,0 +1,43 @@
# Class: tag<T\>
Represents a settings tag that can be accessed at any time by a script.
## Type parameters
Name |
:------ |
`T` |
## Table of contents
### Constructors
- [constructor](tag.md#constructor)
### Methods
- [get](tag.md#get)
## Constructors
### constructor
\+ **new tag**<T\>(): [*tag*](tag.md)<T\>
#### Type parameters:
Name |
:------ |
`T` |
**Returns:** [*tag*](tag.md)<T\>
## Methods
### get
**get**(): T
Returns the current value of this tag in the settings panel.
**Returns:** T

View File

@@ -0,0 +1,64 @@
# Class: tex
Represents a single texture unit in the worlds texture layers.
A texture unit represents the smallest area where it's possible to
affect textures alpha layers. This is much smaller than the areas made
up by heightmap vertices.
## Table of contents
### Constructors
- [constructor](tex.md#constructor)
### Methods
- [get\_alpha](tex.md#get_alpha)
- [get\_pos\_2d](tex.md#get_pos_2d)
- [set\_alpha](tex.md#set_alpha)
## Constructors
### constructor
\+ **new tex**(): [*tex*](tex.md)
**Returns:** [*tex*](tex.md)
## Methods
### get\_alpha
**get_alpha**(`index`: *number*): *number*
#### Parameters:
Name | Type |
:------ | :------ |
`index` | *number* |
**Returns:** *number*
___
### get\_pos\_2d
**get_pos_2d**(): [*vector\_3d*](vector_3d.md)
**Returns:** [*vector\_3d*](vector_3d.md)
___
### set\_alpha
**set_alpha**(`index`: *number*, `alpha`: *number*): *void*
#### Parameters:
Name | Type |
:------ | :------ |
`index` | *number* |
`alpha` | *number* |
**Returns:** *void*

View File

@@ -0,0 +1,42 @@
# Class: vector\_3d
Represents a 3-dimensional vector.
Most functions do not use the 'y' (height) value at all
## Table of contents
### Constructors
- [constructor](vector_3d.md#constructor)
### Properties
- [x](vector_3d.md#x)
- [y](vector_3d.md#y)
- [z](vector_3d.md#z)
## Constructors
### constructor
\+ **new vector_3d**(): [*vector\_3d*](vector_3d.md)
**Returns:** [*vector\_3d*](vector_3d.md)
## Properties
### x
**x**: *number*
___
### y
**y**: *number*
___
### z
**z**: *number*

View File

@@ -0,0 +1,190 @@
# Class: vert
Represents a single heightmap vertex in the world.
Changes to this vertex takes visible effect in Noggit after you call
"apply" on the chunk or selection that contains it.
## Table of contents
### Constructors
- [constructor](vert.md#constructor)
### Methods
- [add\_height](vert.md#add_height)
- [get\_alpha](vert.md#get_alpha)
- [get\_pos](vert.md#get_pos)
- [is\_water\_aligned](vert.md#is_water_aligned)
- [set\_alpha](vert.md#set_alpha)
- [set\_color](vert.md#set_color)
- [set\_height](vert.md#set_height)
- [set\_hole](vert.md#set_hole)
- [set\_water](vert.md#set_water)
- [sub\_height](vert.md#sub_height)
## Constructors
### constructor
\+ **new vert**(): [*vert*](vert.md)
**Returns:** [*vert*](vert.md)
## Methods
### add\_height
**add_height**(`y`: *number*): *any*
#### Parameters:
Name | Type |
:------ | :------ |
`y` | *number* |
**Returns:** *any*
___
### get\_alpha
**get_alpha**(`index`: *number*): *any*
Returns the average alpha of all texture units closest to this vertex.
#### Parameters:
Name | Type |
:------ | :------ |
`index` | *number* |
**Returns:** *any*
___
### get\_pos
**get_pos**(): [*vector\_3d*](vector_3d.md)
Returns the full position of this vertex
**Returns:** [*vector\_3d*](vector_3d.md)
___
### is\_water\_aligned
**is_water_aligned**(): *boolean*
Returns true if this vertex is aligned with water tiles.
**Returns:** *boolean*
___
### set\_alpha
**set_alpha**(`index`: *number*, `alpha`: *number*): *void*
Sets a texture alpha layer of all texture units closest to this vertex.
#### Parameters:
Name | Type |
:------ | :------ |
`index` | *number* |
`alpha` | *number* |
**Returns:** *void*
___
### set\_color
**set_color**(`red`: *number*, `green`: *number*, `blue`: *number*): *void*
Changes the vertex color that this vertex blends with the
underlying texture. Values generally range between 0-1, but can
also go higher.
#### Parameters:
Name | Type | Description |
:------ | :------ | :------ |
`red` | *number* | How much red should be used (default: 1) |
`green` | *number* | How much green should be used (default: 1) |
`blue` | *number* | How much blue should be used (default: 1) |
**Returns:** *void*
___
### set\_height
**set_height**(`y`: *number*): *any*
Changes the height of this vertex
#### Parameters:
Name | Type |
:------ | :------ |
`y` | *number* |
**Returns:** *any*
___
### set\_hole
**set_hole**(`has_hole`: *boolean*): *void*
Sets whether this vertex should be a hole, but only if the
vertex is aligned with hole tiles. If the vertex is not aligned
with a hole tile, this function does nothing.
#### Parameters:
Name | Type |
:------ | :------ |
`has_hole` | *boolean* |
**Returns:** *void*
___
### set\_water
**set_water**(`type`: *number*, `height`: *number*): *void*
Changes the water type on this vertex, but only if the vertex is
aligned with water tiles. If the vertex is not aligned
with a water tile, this function does nothing.
**`note`** The C++ function backing this operation is very slow for the moment.
use with care.
#### Parameters:
Name | Type |
:------ | :------ |
`type` | *number* |
`height` | *number* |
**Returns:** *void*
___
### sub\_height
**sub_height**(`y`: *number*): *any*
#### Parameters:
Name | Type |
:------ | :------ |
`y` | *number* |
**Returns:** *any*

932
scripts/docs/api/modules.md Normal file
View File

@@ -0,0 +1,932 @@
#
## Table of contents
### Classes
- [chunk](classes/chunk.md)
- [image](classes/image.md)
- [model](classes/model.md)
- [noisemap](classes/noisemap.md)
- [procedures\_class](classes/procedures_class.md)
- [random](classes/random.md)
- [script\_brush](classes/script_brush.md)
- [script\_brush\_event](classes/script_brush_event.md)
- [selection](classes/selection.md)
- [tag](classes/tag.md)
- [tex](classes/tex.md)
- [vector\_3d](classes/vector_3d.md)
- [vert](classes/vert.md)
### Type aliases
- [brush\_callback](modules.md#brush_callback)
- [callback](modules.md#callback)
- [nil](modules.md#nil)
### Variables
- [procedures](modules.md#procedures)
### Functions
- [abs](modules.md#abs)
- [acos](modules.md#acos)
- [acosh](modules.md#acosh)
- [add\_m2](modules.md#add_m2)
- [add\_wmo](modules.md#add_wmo)
- [append\_file](modules.md#append_file)
- [asin](modules.md#asin)
- [asinh](modules.md#asinh)
- [atan](modules.md#atan)
- [atanh](modules.md#atanh)
- [brush](modules.md#brush)
- [cam\_pitch](modules.md#cam_pitch)
- [cam\_yaw](modules.md#cam_yaw)
- [camera\_pos](modules.md#camera_pos)
- [cbrt](modules.md#cbrt)
- [ceil](modules.md#ceil)
- [cos](modules.md#cos)
- [cosh](modules.md#cosh)
- [create\_image](modules.md#create_image)
- [dist\_2d](modules.md#dist_2d)
- [dist\_2d\_compare](modules.md#dist_2d_compare)
- [exp](modules.md#exp)
- [floor](modules.md#floor)
- [get\_area\_id](modules.md#get_area_id)
- [get\_chunk](modules.md#get_chunk)
- [get\_map\_id](modules.md#get_map_id)
- [holding\_alt](modules.md#holding_alt)
- [holding\_ctrl](modules.md#holding_ctrl)
- [holding\_left\_mouse](modules.md#holding_left_mouse)
- [holding\_right\_mouse](modules.md#holding_right_mouse)
- [holding\_shift](modules.md#holding_shift)
- [holding\_space](modules.md#holding_space)
- [lerp](modules.md#lerp)
- [load\_png](modules.md#load_png)
- [log](modules.md#log)
- [log10](modules.md#log10)
- [make\_noise](modules.md#make_noise)
- [path\_exists](modules.md#path_exists)
- [pow](modules.md#pow)
- [print](modules.md#print)
- [random\_from\_seed](modules.md#random_from_seed)
- [random\_from\_time](modules.md#random_from_time)
- [read\_file](modules.md#read_file)
- [rotate\_2d](modules.md#rotate_2d)
- [round](modules.md#round)
- [select\_between](modules.md#select_between)
- [select\_origin](modules.md#select_origin)
- [sin](modules.md#sin)
- [sinh](modules.md#sinh)
- [sqrt](modules.md#sqrt)
- [tan](modules.md#tan)
- [tanh](modules.md#tanh)
- [vec](modules.md#vec)
- [write\_file](modules.md#write_file)
## Type aliases
### brush\_callback
Ƭ **brush\_callback**: [*callback*](modules.md#callback)<(`brush`: [*script\_brush*](classes/script_brush.md), `event`: [*script\_brush\_event*](classes/script_brush_event.md)) => *void*\>
The type of callback used for brush events.
**`note`** In lua, the first argument becomes "self" argument if using colon notation
___
### callback
Ƭ **callback**<T\>: T \| [*nil*](modules.md#nil)
Callback functions are unassigned by default, but may be assigned to
by the user
#### Type parameters:
Name |
:------ |
`T` |
___
### nil
Ƭ **nil**: *undefined*
This is the documentation for the Noggit scripting API.
Functions not connected to a class are global and can be called from
anywhere in a script.
## Variables
### procedures
`Const` **procedures**: [*procedures\_class*](classes/procedures_class.md)
singleton
## Functions
### abs
**abs**(`arg`: *number*): *any*
#### Parameters:
Name | Type |
:------ | :------ |
`arg` | *number* |
**Returns:** *any*
___
### acos
**acos**(`a`: *number*): *any*
#### Parameters:
Name | Type |
:------ | :------ |
`a` | *number* |
**Returns:** *any*
___
### acosh
**acosh**(`a`: *number*): *any*
#### Parameters:
Name | Type |
:------ | :------ |
`a` | *number* |
**Returns:** *any*
___
### add\_m2
**add_m2**(`filename`: *string*, `pos`: [*vector\_3d*](classes/vector_3d.md), `scale`: *number*, `rotation`: [*vector\_3d*](classes/vector_3d.md)): *void*
Spawns an m2 model in the world.
#### Parameters:
Name | Type |
:------ | :------ |
`filename` | *string* |
`pos` | [*vector\_3d*](classes/vector_3d.md) |
`scale` | *number* |
`rotation` | [*vector\_3d*](classes/vector_3d.md) |
**Returns:** *void*
___
### add\_wmo
**add_wmo**(`filename`: *string*, `pos`: [*vector\_3d*](classes/vector_3d.md), `rot`: [*vector\_3d*](classes/vector_3d.md)): *void*
Spawns a wmo model in the world.
**`note`** wmo models cannot be scaled.
#### Parameters:
Name | Type |
:------ | :------ |
`filename` | *string* |
`pos` | [*vector\_3d*](classes/vector_3d.md) |
`rot` | [*vector\_3d*](classes/vector_3d.md) |
**Returns:** *void*
___
### append\_file
**append_file**(`file`: *string*, `content`: *string*): *void*
Appends text to a file
**`note`** This operation REQUIRES explicit permission from the user,
or it will throw an error.
#### Parameters:
Name | Type |
:------ | :------ |
`file` | *string* |
`content` | *string* |
**Returns:** *void*
___
### asin
**asin**(`a`: *number*): *any*
#### Parameters:
Name | Type |
:------ | :------ |
`a` | *number* |
**Returns:** *any*
___
### asinh
**asinh**(`a`: *number*): *any*
#### Parameters:
Name | Type |
:------ | :------ |
`a` | *number* |
**Returns:** *any*
___
### atan
**atan**(`a`: *number*): *any*
#### Parameters:
Name | Type |
:------ | :------ |
`a` | *number* |
**Returns:** *any*
___
### atanh
**atanh**(`a`: *number*): *any*
#### Parameters:
Name | Type |
:------ | :------ |
`a` | *number* |
**Returns:** *any*
___
### brush
**brush**(`name`: *string*): [*script\_brush*](classes/script_brush.md)
Creates a new script brush
#### Parameters:
Name | Type |
:------ | :------ |
`name` | *string* |
**Returns:** [*script\_brush*](classes/script_brush.md)
___
### cam\_pitch
**cam_pitch**(): *number*
Returns the cameras pitch rotation (the one you almost NEVER want)
**Returns:** *number*
___
### cam\_yaw
**cam_yaw**(): *number*
Returns the cameras yaw rotation (the one you almost ALWAYS want)
**Returns:** *number*
___
### camera\_pos
**camera_pos**(): [*vector\_3d*](classes/vector_3d.md)
Returns the current camera position
**Returns:** [*vector\_3d*](classes/vector_3d.md)
___
### cbrt
**cbrt**(`a`: *number*): *any*
#### Parameters:
Name | Type |
:------ | :------ |
`a` | *number* |
**Returns:** *any*
___
### ceil
**ceil**(`a`: *number*): *any*
#### Parameters:
Name | Type |
:------ | :------ |
`a` | *number* |
**Returns:** *any*
___
### cos
**cos**(`a`: *number*): *any*
#### Parameters:
Name | Type |
:------ | :------ |
`a` | *number* |
**Returns:** *any*
___
### cosh
**cosh**(`a`: *number*): *any*
#### Parameters:
Name | Type |
:------ | :------ |
`a` | *number* |
**Returns:** *any*
___
### create\_image
**create_image**(`width`: *number*, `height`: *number*): [*image*](classes/image.md)
Creates a new blank image
#### Parameters:
Name | Type |
:------ | :------ |
`width` | *number* |
`height` | *number* |
**Returns:** [*image*](classes/image.md)
___
### dist\_2d
**dist_2d**(`from`: [*vector\_3d*](classes/vector_3d.md), `to`: [*vector\_3d*](classes/vector_3d.md)): *any*
Returns the 2d distance (ignoring y) between two vectors
#### Parameters:
Name | Type |
:------ | :------ |
`from` | [*vector\_3d*](classes/vector_3d.md) |
`to` | [*vector\_3d*](classes/vector_3d.md) |
**Returns:** *any*
___
### dist\_2d\_compare
**dist_2d_compare**(`from`: [*vector\_3d*](classes/vector_3d.md), `to`: [*vector\_3d*](classes/vector_3d.md), `dist`: *number*): *number*
Compares the 2d distance (ignoring y value) between two vectors to a given distance.
This operation is significantly faster than manually comparing to the result of dist_2d
#### Parameters:
Name | Type |
:------ | :------ |
`from` | [*vector\_3d*](classes/vector_3d.md) |
`to` | [*vector\_3d*](classes/vector_3d.md) |
`dist` | *number* |
**Returns:** *number*
___
### exp
**exp**(`a`: *number*): *any*
#### Parameters:
Name | Type |
:------ | :------ |
`a` | *number* |
**Returns:** *any*
___
### floor
**floor**(`a`: *number*): *any*
#### Parameters:
Name | Type |
:------ | :------ |
`a` | *number* |
**Returns:** *any*
___
### get\_area\_id
**get_area_id**(`pos`: [*vector\_3d*](classes/vector_3d.md)): *number*
Returns the area id at a specific position.
The 'y' value is ignored for this operation.
#### Parameters:
Name | Type |
:------ | :------ |
`pos` | [*vector\_3d*](classes/vector_3d.md) |
**Returns:** *number*
___
### get\_chunk
**get_chunk**(`position`: [*vector\_3d*](classes/vector_3d.md)): [*chunk*](classes/chunk.md)
Returns the chunk at a given position.
The tile at the position must be loaded into memory for the
operation to be successful.
#### Parameters:
Name | Type |
:------ | :------ |
`position` | [*vector\_3d*](classes/vector_3d.md) |
**Returns:** [*chunk*](classes/chunk.md)
___
### get\_map\_id
**get_map_id**(): *number*
Returns the id of the currently open map
**Returns:** *number*
___
### holding\_alt
**holding_alt**(): *boolean*
Returns true if the user is currently pressing the alt key
**Returns:** *boolean*
___
### holding\_ctrl
**holding_ctrl**(): *boolean*
Returns true if the user is currently pressing the ctrl key
**Returns:** *boolean*
___
### holding\_left\_mouse
**holding_left_mouse**(): *boolean*
Returns true if the user is currently pressing the left mouse button
**Returns:** *boolean*
___
### holding\_right\_mouse
**holding_right_mouse**(): *boolean*
Returns true if the user is currently pressing the right mouse button
**Returns:** *boolean*
___
### holding\_shift
**holding_shift**(): *boolean*
Returns true if the user is currently pressing the shift key
**Returns:** *boolean*
___
### holding\_space
**holding_space**(): *boolean*
Returns true if the user is currently pressing the spacebar
**Returns:** *boolean*
___
### lerp
**lerp**(`from`: *number*, `to`: *number*, `ratio`: *number*): *number*
Returns the value at some percentage between two values.
#### Parameters:
Name | Type | Description |
:------ | :------ | :------ |
`from` | *number* | the minimum range value |
`to` | *number* | the maximum range value |
`ratio` | *number* | the percentage to take (typically between 0-1) |
**Returns:** *number*
___
### load\_png
**load_png**(`path`: *string*): [*image*](classes/image.md)
Loads a png file into an in-memory image.
#### Parameters:
Name | Type |
:------ | :------ |
`path` | *string* |
**Returns:** [*image*](classes/image.md)
___
### log
**log**(`a`: *number*): *any*
#### Parameters:
Name | Type |
:------ | :------ |
`a` | *number* |
**Returns:** *any*
___
### log10
**log10**(`a`: *number*): *any*
#### Parameters:
Name | Type |
:------ | :------ |
`a` | *number* |
**Returns:** *any*
___
### make\_noise
**make_noise**(`start_x`: *number*, `start_y`: *number*, `width`: *number*, `height`: *number*, `frequency`: *number*, `algorithm`: *string*, `seed`: *string*): *any*
Creates a new noisemap
#### Parameters:
Name | Type |
:------ | :------ |
`start_x` | *number* |
`start_y` | *number* |
`width` | *number* |
`height` | *number* |
`frequency` | *number* |
`algorithm` | *string* |
`seed` | *string* |
**Returns:** *any*
___
### path\_exists
**path_exists**(`path`: *string*): *boolean*
Returns true if a pathname exists already
#### Parameters:
Name | Type |
:------ | :------ |
`path` | *string* |
**Returns:** *boolean*
___
### pow
**pow**(`a1`: *number*, `a2`: *number*): *any*
#### Parameters:
Name | Type |
:------ | :------ |
`a1` | *number* |
`a2` | *number* |
**Returns:** *any*
___
### print
**print**(): *void*
**Returns:** *void*
**print**(...`args`: *any*[]): *any*
Prints out a message to the script window.
(sometimes, with errors, print messages will be suppressed)
#### Parameters:
Name | Type |
:------ | :------ |
`...args` | *any*[] |
**Returns:** *any*
___
### random\_from\_seed
**random_from_seed**(`seed`: *string*): [*random*](classes/random.md)
Creates a new random generator from a specific seed.
#### Parameters:
Name | Type |
:------ | :------ |
`seed` | *string* |
**Returns:** [*random*](classes/random.md)
___
### random\_from\_time
**random_from_time**(): [*random*](classes/random.md)
Creates a new random generator from the current system time.
**Returns:** [*random*](classes/random.md)
___
### read\_file
**read_file**(`file`: *string*): *string*
Reads a file from the file system.
**`note`** This operation does NOT require explicit permission from the user.
#### Parameters:
Name | Type |
:------ | :------ |
`file` | *string* |
**Returns:** *string*
___
### rotate\_2d
**rotate_2d**(`point`: [*vector\_3d*](classes/vector_3d.md), `origin`: [*vector\_3d*](classes/vector_3d.md), `angle`: *number*): [*vector\_3d*](classes/vector_3d.md)
Returns a 3d point around an origin, ignoring the y value.
#### Parameters:
Name | Type |
:------ | :------ |
`point` | [*vector\_3d*](classes/vector_3d.md) |
`origin` | [*vector\_3d*](classes/vector_3d.md) |
`angle` | *number* |
**Returns:** [*vector\_3d*](classes/vector_3d.md)
___
### round
**round**(`a`: *number*): *any*
#### Parameters:
Name | Type |
:------ | :------ |
`a` | *number* |
**Returns:** *any*
___
### select\_between
**select_between**(`point1`: [*vector\_3d*](classes/vector_3d.md), `point2`: [*vector\_3d*](classes/vector_3d.md)): [*selection*](classes/selection.md)
Makes and returns a rectangular selection between two points.
#### Parameters:
Name | Type |
:------ | :------ |
`point1` | [*vector\_3d*](classes/vector_3d.md) |
`point2` | [*vector\_3d*](classes/vector_3d.md) |
**Returns:** [*selection*](classes/selection.md)
___
### select\_origin
**select_origin**(`origin`: [*vector\_3d*](classes/vector_3d.md), `xRadius`: *number*, `zRadius`: *number*): [*selection*](classes/selection.md)
Makes and returns a rectangular selection around an origin point
#### Parameters:
Name | Type | Description |
:------ | :------ | :------ |
`origin` | [*vector\_3d*](classes/vector_3d.md) | The center point of the selection |
`xRadius` | *number* | |
`zRadius` | *number* | |
**Returns:** [*selection*](classes/selection.md)
selection
___
### sin
**sin**(`a`: *number*): *any*
#### Parameters:
Name | Type |
:------ | :------ |
`a` | *number* |
**Returns:** *any*
___
### sinh
**sinh**(`a`: *number*): *any*
#### Parameters:
Name | Type |
:------ | :------ |
`a` | *number* |
**Returns:** *any*
___
### sqrt
**sqrt**(`arg`: *number*): *any*
#### Parameters:
Name | Type |
:------ | :------ |
`arg` | *number* |
**Returns:** *any*
___
### tan
**tan**(`a`: *number*): *any*
#### Parameters:
Name | Type |
:------ | :------ |
`a` | *number* |
**Returns:** *any*
___
### tanh
**tanh**(`a`: *number*): *any*
#### Parameters:
Name | Type |
:------ | :------ |
`a` | *number* |
**Returns:** *any*
___
### vec
**vec**(`x`: *number*, `y`: *number*, `z`: *number*): [*vector\_3d*](classes/vector_3d.md)
Creates a new vector from its components
#### Parameters:
Name | Type |
:------ | :------ |
`x` | *number* |
`y` | *number* |
`z` | *number* |
**Returns:** [*vector\_3d*](classes/vector_3d.md)
___
### write\_file
**write_file**(`file`: *string*, `content`: *string*): *void*
Writes text to a file
**`note`** This operation REQUIRES explicit permission from the user,
or it will throw an error.
#### Parameters:
Name | Type |
:------ | :------ |
`file` | *string* |
`content` | *string* |
**Returns:** *void*

867
scripts/global.d.ts vendored Normal file
View File

@@ -0,0 +1,867 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
/**
* This is the documentation for the Noggit scripting API.
* Functions not connected to a class are global and can be called from
* anywhere in a script.
*/
// While the language in this file is TypeScript,
// everything here applies to lua as well.
type nil = undefined;
/**
* Callback functions are unassigned by default, but may be assigned to
* by the user
*/
type callback<T> = T|nil
/**
* The type of callback used for brush events.
*
* @note In lua, the first argument becomes "self" argument if using colon notation
*/
type brush_callback = callback<((brush: script_brush, event: script_brush_event) => void)>;
/**
* Represents a 3-dimensional vector.
* Most functions do not use the 'y' (height) value at all
*/
declare class vector_3d {
x: number;
y: number;
z: number;
}
/**
* Represents the event context passed to brush click events.
*/
declare class script_brush_event {
/**
* Sets the outer radius in the settings panel for this brush
* @param value
*/
set_outer_radius(value: number);
/**
* Sets the outer radius in the settings panel for this brush
* @param value - should be between 0-1
*/
set_inner_radius(value: number);
/**
* Returns the current outer radius configured in the settings panel
*/
outer_radius(): number;
/**
* Returns the current inner radius configured in the settings panel
*/
inner_radius(): number;
/**
* Returns the delta-time since the last update frame
*/
dt(): number;
/**
* Returns world position of this click event.
* i.e. the world position where the user clicked, held or released a mouse button
*/
pos(): vector_3d;
}
/**
* Represents a script brush in the script window.
*/
declare class script_brush {
/**
* Changes the name of this script brush
* @param name
*/
set_name(name: string): void;
/**
* Returns the current name of this script brush
*/
get_name(): string;
/**
* Adds an empty tag, typically used to create empty lines in the settings panel
*/
add_null_tag();
/**
* Adds a description row to the brush window
* @param text
*/
add_description(text: string);
/**
* Adds an integer tag to the settings panel
* @param item
* @param low
* @param high
* @param def
*/
add_int_tag(item: string, low: number, high: number, def: number): tag<number>;
/**
* Adds a real (i.e. float) tag to the settings panel
* @param item
* @param low
* @param high
* @param def
*/
add_real_tag(item: string, low: number, high: number, def: number): tag<number>;
/**
* Adds a string tag to the settings panel
* @param item
* @param def
*/
add_string_tag(item: string, def: string): tag<string>;
/**
* Adds a bool tag to the settings panel
* @param item
* @param def
*/
add_bool_tag(item: string, def: boolean): tag<boolean>;
/**
* Adds a dropdown menu to the settings panel
* @param item
* @param values
*/
add_string_list_tag(item: string, ...values: string[]): tag<string>;
/**
* The function to call when the user left clicks
* the world with this brush
*/
on_left_click: brush_callback;
/**
* The funciton to call when the user holds the left mouse button
* in the world with this brush
*/
on_left_hold: brush_callback;
/**
* The function to call when the user releases the left moues button
* in the world with this brush
*/
on_left_release: brush_callback;
/**
* The function to call when the user right clicks
* the world with this brush
*/
on_right_click: brush_callback;
/**
* The funciton to call when the user holds the right mouse button
* in the world with this brush
*/
on_right_hold: brush_callback;
/**
* The function to call when the user releases the right mouse button
* in the world with this brush
*/
on_right_release: brush_callback;
}
/**
* Creates a new script brush
* @param name
*/
declare function brush(name: string): script_brush;
/**
* Represents a chunk in the world
*/
declare class chunk {
/**
* Removes a texture layer from this chunk
* and decreases the texture ids of all higher layers by 1
* @param index
*/
remove_texture(index: number): void;
/**
* Returns the name of the texture at the specified layer.
* @param index
*/
get_texture(index: number): string;
/**
* Returns the amount of textures on this chunk
*/
get_texture_count(): number
/**
* Adds a new texture at the current topmost layer.
*
* @param texture
* @param effect - effect id to add
* - -2 (default): does not change effect
* - -1: clears current effect index
* - 0+: change to this effect index
* @note A chunk can hold at most 4 texture layers.
* @return texture index added to
*/
add_texture(texture: string, effect: number): number;
/**
* Changes the effect id at a texture layer
* @param layer
* @param effect - effect id to set (-1 to remove effects)
*/
set_effect(layer: number, effect: number)
/**
* Returns the effect id at a texture layer
* @param layer
*/
get_effect(layer: number): number
/**
* Removes all texture layers in this chunk
*/
clear_textures(): void;
/**
* Creates or removes a hole in this chunk
* @param hole
*/
set_hole(hole: boolean): void;
/**
* Removes all vertex colors in this chunk
*/
clear_colors(): void;
/**
* Applies all changes to texture alphamaps in this chunk
*/
apply_textures(): void;
/**
* Applies all changes to the heightmap in this chunk
*/
apply_heightmap(): void;
/**
* Applies all changes to vertex colors in this chunk
*/
apply_vertex_color(): void;
/**
* Applies all changes in this chunk
*/
apply_all(): void;
/**
* Same as apply_all
*/
apply(): void;
/**
* Sets whether this chunk should be impassable for players or not
*/
set_impassable(impassable: boolean): void;
/**
* Returns the area id of a chunk
*/
get_area_id(): number;
/**
* Changes the area id of a chunk
* @param value
*/
set_area_id(value: number): void;
/**
* Returns a selection spanning this chunk
*
* @note - iterating will include border vert/texels
*/
to_selection(): selection;
/**
* Returns a texel by index in this chunk
* @param index valid in range [0-4095]
*/
get_tex(index: number): tex;
/**
* Returns a vertex by index in this chunk
* @param index valid in range [0-144]
*/
get_vert(index: number): vert;
}
/**
* Writes text to a file
* @param file
* @param content
*
* @note This operation REQUIRES explicit permission from the user,
* or it will throw an error.
*/
declare function write_file(file: string, content: string): void;
/**
* Appends text to a file
* @param file
* @param content
*
* @note This operation REQUIRES explicit permission from the user,
* or it will throw an error.
*/
declare function append_file(file: string, content: string): void;
/**
* Reads a file from the file system.
* @param file
* @note This operation does NOT require explicit permission from the user.
*/
declare function read_file(file: string): string;
/**
* Returns true if a pathname exists already
* @param path
*/
declare function path_exists(path: string): boolean;
/**
* Creates a new vector from its components
* @param x
* @param y
* @param z
*/
declare function vec(x: number, y: number, z: number): vector_3d;
/**
* Returns the current camera position
*/
declare function camera_pos(): vector_3d;
/**
* Spawns an m2 model in the world.
*
* @param filename
* @param pos
* @param scale
* @param rotation
*/
declare function add_m2(filename: string
, pos: vector_3d
, scale: number
, rotation: vector_3d
): void
/**
* Spawns a wmo model in the world.
*
* @param filename
* @param pos
* @param rot
*
* @note wmo models cannot be scaled.
*/
declare function add_wmo( filename: string
, pos: vector_3d
, rot: vector_3d
): void
/**
* Returns the id of the currently open map
*/
declare function get_map_id(): number
/**
* Returns the area id at a specific position.
*
* The 'y' value is ignored for this operation.
*/
declare function get_area_id(pos: vector_3d): number
/**
* Returns the cameras pitch rotation (the one you almost NEVER want)
*/
declare function cam_pitch(): number
/**
* Returns the cameras yaw rotation (the one you almost ALWAYS want)
*/
declare function cam_yaw(): number
/**
* Returns true if the user is currently pressing the alt key
*/
declare function holding_alt(): boolean
/**
* Returns true if the user is currently pressing the shift key
*/
declare function holding_shift(): boolean
/**
* Returns true if the user is currently pressing the ctrl key
*/
declare function holding_ctrl(): boolean
/**
* Returns true if the user is currently pressing the spacebar
*/
declare function holding_space(): boolean
/**
* Returns true if the user is currently pressing the left mouse button
*/
declare function holding_left_mouse(): boolean
/**
* Returns true if the user is currently pressing the right mouse button
*/
declare function holding_right_mouse(): boolean
/**
* Prints out a message to the script window.
* (sometimes, with errors, print messages will be suppressed)
* @param args
*/
declare function print(...args: any[])
/**
* Represents a bitmap image
*
* images can be created from create_image or load_png
*/
declare class image {
/**
* Returns the pixel value at a coordinate
* @param x
* @param y
*/
get_pixel(x: number, y: number): number;
/**
* Returns the blue channel (between 0-1) at an image coordinate
* @param x
* @param y
*/
get_blue(x: number, y: number): number;
/**
* Returns the alpha channel (between 0-1) at an image coordinate
* @param x
* @param y
*/
get_alpha(x: number, y: number): number;
/**
* Returns the red channel (between 0-1) at an image coordinate
* @param x
* @param y
*/
get_red(x: number, y: number): number;
/**
* Returns the green channel (between 0-1) at an image coordinate
* @param x
* @param y
*/
get_green(x: number, y: number): number;
/**
* Returns the pixel value at a relative horizontal coordinate
* @param rel horizontal relative position (between 0-1)
*/
gradient_scale(rel: number): number;
/**
* Sets the pixel value at an image coordinate
* @param x
* @param y
* @param value
*/
set_pixel(x: number, y: number, value: number): void;
/**
* Sets the pixel value at an image coordinate
* @param x
* @param y
* @param r - should be between 0-1
* @param g - should be between 0-1
* @param b - should be between 0-1
* @param a - should be between 0-1
*/
set_pixel_floats(x: number, y: number, r: number, g: number, b: number, a: number): void;
/**
* Saves this image to a file
* @param filename
*/
save(filename: string);
/**
* Returns the width of this image
*/
width(): number;
/**
* Returns the height of this image
*/
height(): number;
}
/**
* Creates a new blank image
* @param width
* @param height
*/
declare function create_image(width: number, height: number): image;
/**
* Loads a png file into an in-memory image.
* @param path
*/
declare function load_png(path: string): image;
declare function round(a: number);
declare function pow(a1: number, a2: number)
declare function log10(a: number);
declare function log(a: number);
declare function ceil(a: number);
declare function floor(a: number);
declare function exp(a: number);
declare function cbrt(a: number);
declare function acosh(a: number);
declare function asinh(a: number);
declare function atanh(a: number);
declare function cosh(a: number);
declare function sinh(a: number);
declare function tanh(a: number);
declare function acos(a: number);
declare function asin(a: number);
declare function atan(a: number);
declare function cos(a: number);
declare function sin(a: number);
declare function tan(a: number);
declare function sqrt(arg: number);
declare function abs(arg: number);
/**
* Returns the value at some percentage between two values.
*
* @param from - the minimum range value
* @param to - the maximum range value
* @param ratio - the percentage to take (typically between 0-1)
*/
declare function lerp(from: number, to: number, ratio: number): number;
/**
* Returns the 2d distance (ignoring y) between two vectors
* @param from
* @param to
*/
declare function dist_2d(from: vector_3d, to: vector_3d);
/**
* Compares the 2d distance (ignoring y value) between two vectors to a given distance.
* This operation is significantly faster than manually comparing to the result of dist_2d
*
* @param from
* @param to
* @param dist
*/
declare function dist_2d_compare(from: vector_3d, to:vector_3d, dist: number): number
/**
* Returns a 3d point around an origin, ignoring the y value.
* @param point
* @param origin
* @param angle
*/
declare function rotate_2d(point: vector_3d, origin: vector_3d, angle: number): vector_3d
/**
* Represents a model in the world. Can represent both an m2 and wmo model.
*/
declare class model {
get_pos(): vector_3d;
set_pos(pos: vector_3d): void;
get_rot(): vector_3d;
set_rot(pos: vector_3d): void;
get_scale(): number;
set_scale(scale: number): void;
get_uid(): number;
remove(): void;
get_filename(): string;
has_filename(name: string): boolean;
replace(filename: string);
}
/**
* Represents a map of floats values, typically use with a
* noise generator.
*/
declare class noisemap {
/**
* Returns the float value at a specific 3d position.
* @param pos
* @note The 'y' value of pos is ignored by this operation.
*/
get(pos: vector_3d): number;
/**
* Returns true if the float value at a 3d position
* is the highest position within a given range.
*
* This is typically used for object placement.
*
* @param pos
* @param check_radius
*/
is_highest(pos: vector_3d, check_radius: number): boolean
set(x: number, y: number, value: number): void;
width(): number;
height(): number;
}
/**
* Creates a new noisemap
* @param start_x
* @param start_y
* @param width
* @param height
* @param frequency
* @param algorithm
* @param seed
*/
declare function make_noise(start_x: number, start_y: number, width: number, height: number, frequency: number, algorithm: string, seed: string)
/**
* Represents a random generator and its state.
*/
declare class random {
integer(low: number, high: number): number;
real(low: number, high: number): number;
}
/**
* Creates a new random generator from a specific seed.
* @param seed
*/
declare function random_from_seed(seed: string): random;
/**
* Creates a new random generator from the current system time.
*/
declare function random_from_time(): random;
/**
* Represents a rectangular selection in the world and provides
* iterators for heightmap vertices, texture units, chunks and models within it.
*/
declare class selection {
/**
* Creates a noisemap matching the location of this selection
*
* @param frequency
* @param algorithm
* @param seed
*/
make_noise(frequency: number, algorithm: string, seed: string): noisemap
/**
* Returns the center point of this selection
*/
center(): vector_3d;
/**
* Returns the smallest point of this selection
*/
min(): vector_3d;
/**
* Returns the highest point of this selection
*/
max(): vector_3d;
/**
* Returns a vector representing the size of this selection on each axis.
* @note for iterators, only x and z values are respected. y (height) is ignored.
*/
size(): vector_3d;
/**
* Creates and returns an iterator for all models inside this selection
*/
models(): model[];
/**
* Creates and returns an iterator for all vertices inside this selection
*/
verts(): vert[];
/**
* Creates and returns an iterator for all texture units inside this selection
*/
tex(): tex[];
/**
* Creates and returns an iterator for all chunks inside this selection
*/
chunks(): chunk[];
/**
* Applies all changes made inside this selection.
* You almost always want to call this function when you're done
* with a selection.
*/
apply(): void;
}
/**
* Makes and returns a rectangular selection between two points.
* @param point1
* @param point2
*/
declare function select_between(point1: vector_3d, point2: vector_3d): selection;
/**
* Makes and returns a rectangular selection around an origin point
*
* @param origin - The center point of the selection
* @param xRadius
* @param zRadius
* @returns selection
*/
declare function select_origin(origin: vector_3d, xRadius: number, zRadius: number): selection;
/**
* Returns the chunk at a given position.
* The tile at the position must be loaded into memory for the
* operation to be successful.
* @param position
*/
declare function get_chunk(position: vector_3d): chunk
/**
* Represents a settings tag that can be accessed at any time by a script.
*/
declare class tag<T> {
/**
* Returns the current value of this tag in the settings panel.
*/
get(): T;
}
/**
* Represents a single texture unit in the worlds texture layers.
*
* A texture unit represents the smallest area where it's possible to
* affect textures alpha layers. This is much smaller than the areas made
* up by heightmap vertices.
*/
declare class tex {
set_alpha(index: number, alpha: number): void;
get_alpha(index: number): number;
get_pos_2d(): vector_3d;
}
/**
* Represents a single heightmap vertex in the world.
*
* Changes to this vertex takes visible effect in Noggit after you call
* "apply" on the chunk or selection that contains it.
*/
declare class vert {
/**
* Returns the full position of this vertex
*/
get_pos(): vector_3d;
/**
* Changes the height of this vertex
*/
set_height(y: number);
add_height(y: number);
sub_height(y: number);
/**
* Changes the vertex color that this vertex blends with the
* underlying texture. Values generally range between 0-1, but can
* also go higher.
*
* @param red - How much red should be used (default: 1)
* @param green - How much green should be used (default: 1)
* @param blue - How much blue should be used (default: 1)
*/
set_color(red: number, green: number, blue: number): void;
/**
* Changes the water type on this vertex, but only if the vertex is
* aligned with water tiles. If the vertex is not aligned
* with a water tile, this function does nothing.
*
* @param type
* @param height
*
* @note The C++ function backing this operation is very slow for the moment.
* use with care.
*/
set_water(type: number, height: number): void;
/**
* Sets whether this vertex should be a hole, but only if the
* vertex is aligned with hole tiles. If the vertex is not aligned
* with a hole tile, this function does nothing.
*
* @param has_hole
*/
set_hole(has_hole: boolean): void;
/**
* Sets a texture alpha layer of all texture units closest to this vertex.
*
* @param index
* @param alpha
*/
set_alpha(index: number, alpha: number): void;
/**
* Returns the average alpha of all texture units closest to this vertex.
* @param index
*/
get_alpha(index: number);
/**
* Returns true if this vertex is aligned with water tiles.
*/
is_water_aligned(): boolean;
}
/**
* Contains some general-purpose procedures that don't fit anywhere else.
*
* Access these functions through the global singleton "procedures".
*/
declare class procedures_class {
paint_texture(sel: selection, img: image, layer: number, pressure: number, angle: number);
}
/**
* singleton
*/
declare const procedures: procedures_class;

27
scripts/height_noise.lua Normal file
View File

@@ -0,0 +1,27 @@
-- This file is part of Noggit3, licensed under GNU General Public License (version 3).
local noise_brush = brush("Height Noise")
local algo = noise_brush:add_string_tag("Algorithm","HgANAAUAAAAAAABAEAAAAAA/CAAAAACAPwAAAAA/AAAAAAABEwBI4RpAGwANAAMAAAAAAABACAAAAAAAPwAAAAAAAI/C9Tw=")
local seed = noise_brush:add_string_tag("Seed","noggit")
local frequency = noise_brush:add_real_tag("Frequency",0.0005,1.0,0.001,5)
local amplitude = noise_brush:add_real_tag("Amplitude",1.0,1000.0,410.0,2)
function noise_brush:on_left_hold(evt)
local sel = select_origin(
evt:pos(),
evt:outer_radius(),
evt:outer_radius()
)
local map = sel:make_noise(
frequency:get(),
algo:get(),
seed:get()
)
for i,vert in pairs(sel:verts()) do
local height = map:get(
vert:get_pos()
) * amplitude:get()
vert:set_height(height)
end
sel:apply()
end

38
scripts/image_brush.lua Normal file
View File

@@ -0,0 +1,38 @@
-- This file is part of Noggit3, licensed under GNU General Public License (version 3).
local painter_brush = brush("Image Painter")
local image_path = painter_brush:add_string_tag("Filename", "")
function painter_brush:on_left_click(evt)
local img = load_png(
image_path:get()
)
local origin = evt:pos()
local width = img:width()
local height = img:height()
local half_width = width / 2
local half_height = height / 2
local sel = select_origin(origin, width, height)
for i,vert in pairs(sel:verts()) do
local angle = cam_yaw() - 90
local pos = rotate_2d(
vert:get_pos(),
origin,
angle
)
local local_x = round((pos.x - origin.x) + half_width)
local local_z = round((pos.z - origin.z) + half_height)
if local_x >= 0
and local_x < width
and local_z >= 0
and local_z < height
and img:get_alpha(local_x,local_z)>0.5 then
local red = img:get_red(local_x, local_z)
local green = img:get_green(local_x, local_z)
local blue = img:get_blue(local_x, local_z)
vert:set_color(red, green, blue)
end
end
sel:apply()
end

88
scripts/prop_placer.lua Normal file
View File

@@ -0,0 +1,88 @@
-- This file is part of Noggit3, licensed under GNU General Public License (version 3).
local prop_placer = brush("Prop Placer")
local seed = prop_placer:add_string_tag("Seed","noggit")
local dist = prop_placer:add_int_tag("Distance",1,50,5)
local delete_all = prop_placer:add_bool_tag("Delete all models",false)
local circle_brush = prop_placer:add_bool_tag("Circle brush",false)
function Prop(index)
local prop = {}
prop.model_name = prop_placer:add_string_tag("Prop "..index)
prop.min_scale = prop_placer:add_real_tag("Prop "..index.." Min Scale",0.001,10,0.7,2)
prop.max_scale = prop_placer:add_real_tag("Prop "..index.." Max Scale",0.001,10,0.7,2)
return prop
end
prop_placer:add_null_tag()
local prop1 = Prop(1);
prop_placer:add_null_tag();
local prop2 = Prop(2);
prop_placer:add_null_tag();
local prop3 = Prop(3);
local props = {prop1,prop2,prop3}
function prop_placer:on_left_hold(evt)
local cur_props = {}
local count = 0
for _,v in pairs(props) do
if string.len(v.model_name:get())>0 then
table.insert(cur_props,v)
count = count + 1
end
end
if count == 0 then
print("No models selected")
return
end
local sel = select_origin(evt:pos(),evt:outer_radius(),evt:outer_radius())
for _,v in pairs(cur_props) do
for i,model in pairs(sel:models()) do
if(
(delete_all:get() or model:has_filename(v))
and
((not circle_brush:get())
or dist_2d(
model:get_pos()
, evt:pos()) < evt:outer_radius())
) then
model:remove()
end
end
end
local map = make_noise(
sel:min().x-dist:get()
, sel:min().z-dist:get()
, sel:size().x+2*dist:get()
, sel:size().z+2*dist:get()
, 1
, "SIMPLEX"
, seed:get()
)
for i,vert in pairs(sel:verts()) do
if (not circle_brush:get()) or dist_2d(
vert:get_pos(),
evt:pos()
) < evt:outer_radius() then
local loc = vert:get_pos()
if map:is_highest(loc,dist:get()) then
local rnd = random_from_seed(seed:get().." "..loc.x.." "..loc.z)
local index = rnd:integer(1,count+1)
local prop = cur_props[index]
local size = rnd:real(prop.min_scale:get(),prop.max_scale:get())
local rot = rnd:real(0,360.0)
add_m2(prop.model_name:get(),loc,size,vec(0,rot,0))
end
end
end
sel:apply()
end

23
scripts/texture_brush.lua Normal file
View File

@@ -0,0 +1,23 @@
local texture_brush = brush("Texture Brush")
texture_brush:add_description("<b>Description</b>:")
texture_brush:add_description("- Uses a black / white texture to paint alpha layers. ")
texture_brush:add_description("- The painting is only additive at the moment,")
texture_brush:add_description(" meaning it cannot paint layers from \"underneath\"")
texture_brush:add_description(" another layer.")
local texture = texture_brush:add_string_tag("Brush Texture", "")
local pressure = texture_brush:add_real_tag("Pressure", 0, 1000, 1, 2)
local index = texture_brush:add_int_tag("Texture Index", 1, 3, 1)
texture_brush.on_left_hold = function(brush, evt)
local image = load_png(
texture:get()
)
local sel = select_origin(
evt:pos(),
evt:outer_radius(),
evt:outer_radius()
)
procedures:paint_texture(sel,image,index:get(),pressure:get(),cam_yaw()-90)
sel:apply()
end

View File

@@ -0,0 +1,26 @@
local texture_printer = brush("Texture Printer");
texture_printer:add_description("<b>Description</b>:")
texture_printer:add_description("Prints out texture paths and effect ids ")
texture_printer:add_description("in the clicked chunk.")
texture_printer:add_null_tag()
function texture_printer:on_left_click(evt)
local sel = select_origin(evt:pos(), 1, 1)
for i,chunk in pairs(sel:chunks()) do
if chunk:get_texture_count() == 0 then
print("Chunk has no textures")
end
print("== Chunk Textures ==")
for i=0,chunk:get_texture_count()-1 do
local tex = chunk:get_texture(i)
local eff = chunk:get_effect(i)
print("Layer "..i..":")
print(" Texture: "..tex)
print(" Effect: "..eff)
end
print("")
end
end

21
scripts/tsconfig.json Normal file
View File

@@ -0,0 +1,21 @@
/**
* This file has a working configuration to write
* script brushes with TypeScriptToLua
* (https://github.com/TypeScriptToLua/TypeScriptToLua)
*/
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"outDir": "./_tsbuild",
"forceConsistentCasingInFileNames": true
},
"tstl": {
"luaTarget": "5.1",
"luaPlugins": [],
"noImplicitSelf": true,
}
}

View File

@@ -35,11 +35,11 @@ struct ChunkInstanceData
ivec4 ChunkTextureSamplers;
ivec4 ChunkTextureArrayIDs;
ivec4 ChunkHoles_DrawImpass_TexLayerCount_CantPaint;
vec4 ChunkTexAnim_0_1;
vec4 ChunkTexAnim_2_3;
vec4 AreaIDColor_DrawSelection;
ivec4 ChunkTexDoAnim;
ivec4 ChunkTexAnimSpeed;
ivec4 AreaIDColor_Pad2_DrawSelection;
vec4 ChunkXYZBase_Pad1;
vec4 pad2;
ivec4 ChunkTexAnimDir;
};
layout (std140) uniform chunk_instances
@@ -51,7 +51,6 @@ uniform sampler2DArray shadowmap;
uniform sampler2DArray alphamap;
uniform sampler2D stamp_brush;
uniform sampler2DArray textures[11];
uniform vec3 camera;
uniform int draw_cursor_circle;
@@ -63,6 +62,10 @@ uniform vec4 cursor_color;
in vec3 vary_position;
in vec2 vary_texcoord;
in vec2 vary_t0_uv;
in vec2 vary_t1_uv;
in vec2 vary_t2_uv;
in vec2 vary_t3_uv;
in vec3 vary_normal;
in vec3 vary_mccv;
flat in int instanceID;
@@ -75,6 +78,14 @@ const float HOLESIZE = CHUNKSIZE * 0.25;
const float UNITSIZE = HOLESIZE * 0.5;
const float PI = 3.14159265358979323846;
vec3 random_color(float areaID)
{
float r = fract(sin(dot(vec2(areaID), vec2(12.9898, 78.233))) * 43758.5453);
float g = fract(sin(dot(vec2(areaID), vec2(11.5591, 70.233))) * 43569.5451);
float b = fract(sin(dot(vec2(areaID), vec2(13.1234, 76.234))) * 43765.5452);
return vec3(r, g, b);
}
vec3 get_tex_color(vec2 tex_coord, int tex_sampler, int array_index)
{
@@ -133,17 +144,13 @@ vec4 texture_blend()
float a1 = alpha.g;
float a2 = alpha.b;
/*
vec3 t0 = get_tex_color(vary_texcoord + instances[instanceID].ChunkTexAnim_0_1.rg, 0);
vec3 t1 = get_tex_color(vary_texcoord + instances[instanceID].ChunkTexAnim_0_1.ba, 1);
vec3 t2 = get_tex_color(vary_texcoord + instances[instanceID].ChunkTexAnim_2_3.rg, 2);
vec3 t3 = get_tex_color(vary_texcoord + instances[instanceID].ChunkTexAnim_2_3.ba, 3);
*/
vec3 t0 = get_tex_color(vary_t0_uv, instances[instanceID].ChunkTextureSamplers.x, instances[instanceID].ChunkTextureArrayIDs.x);
vec3 t0 = get_tex_color(vary_texcoord, instances[instanceID].ChunkTextureSamplers.x, instances[instanceID].ChunkTextureArrayIDs.x);
vec3 t1 = get_tex_color(vary_texcoord, instances[instanceID].ChunkTextureSamplers.y, instances[instanceID].ChunkTextureArrayIDs.y);
vec3 t2 = get_tex_color(vary_texcoord, instances[instanceID].ChunkTextureSamplers.z, instances[instanceID].ChunkTextureArrayIDs.z);
vec3 t3 = get_tex_color(vary_texcoord, instances[instanceID].ChunkTextureSamplers.w, instances[instanceID].ChunkTextureArrayIDs.w);
vec3 t1 = get_tex_color(vary_t1_uv, instances[instanceID].ChunkTextureSamplers.y, instances[instanceID].ChunkTextureArrayIDs.y);
vec3 t2 = get_tex_color(vary_t2_uv, instances[instanceID].ChunkTextureSamplers.z, instances[instanceID].ChunkTextureArrayIDs.z);
vec3 t3 = get_tex_color(vary_t3_uv, instances[instanceID].ChunkTextureSamplers.w, instances[instanceID].ChunkTextureArrayIDs.w);
return vec4 (t0 * (1.0 - (a0 + a1 + a2)) + t1 * a0 + t2 * a1 + t3 * a2, 1.0);
}
@@ -196,7 +203,7 @@ void main()
if(draw_areaid_overlay != 0)
{
out_color.rgb = out_color.rgb * 0.3 + instances[instanceID].AreaIDColor_DrawSelection.rgb;
out_color.rgb = out_color.rgb * 0.3 + random_color(instances[instanceID].AreaIDColor_Pad2_DrawSelection.r);
}
if(instances[instanceID].ChunkHoles_DrawImpass_TexLayerCount_CantPaint.g != 0) // draw impass
@@ -204,7 +211,7 @@ void main()
out_color.rgb = mix(vec3(1.0), out_color.rgb, 0.5);
}
if(instances[instanceID].AreaIDColor_DrawSelection.a != 0) // draw selection
if(instances[instanceID].AreaIDColor_Pad2_DrawSelection.a != 0) // draw selection
{
out_color.rgb = mix(vec3(1.0), out_color.rgb, 0.5);
}

View File

@@ -15,11 +15,11 @@ struct ChunkInstanceData
ivec4 ChunkTextureSamplers;
ivec4 ChunkTextureArrayIDs;
ivec4 ChunkHoles_DrawImpass_TexLayerCount_CantPaint;
vec4 ChunkTexAnim_0_1;
vec4 ChunkTexAnim_2_3;
vec4 AreaIDColor_DrawSelection;
ivec4 ChunkTexDoAnim;
ivec4 ChunkTexAnimSpeed;
ivec4 AreaIDColor_Pad2_DrawSelection;
vec4 ChunkXYZBase_Pad1;
vec4 pad2;
ivec4 ChunkTexAnimDir;
};
layout (std140) uniform chunk_instances
@@ -29,11 +29,17 @@ layout (std140) uniform chunk_instances
uniform sampler2D heightmap;
uniform sampler2D mccv;
uniform int base_instance;
uniform int animtime;
out vec3 vary_position;
out vec2 vary_texcoord;
out vec3 vary_normal;
out vec2 vary_t0_uv;
out vec2 vary_t1_uv;
out vec2 vary_t2_uv;
out vec2 vary_t3_uv;
out vec3 vary_mccv;
out vec3 vary_normal;
flat out int instanceID;
bool isHoleVertex(uint vertexId, uint hole)
@@ -88,13 +94,26 @@ float makeNaN(float nonneg)
return sqrt(-nonneg-1.0);
}
vec2 animUVOffset(int do_animate, int spd, int dir)
{
const float texanimxtab[8] = float[8]( 0, 1, 1, 1, 0, -1, -1, -1 );
const float texanimytab[8] = float[8]( 1, 1, 0, -1, -1, -1, 0, 1 );
float fdx = -texanimxtab[dir];
float fdy = texanimytab[dir];
int animspd = int(200 * 8.0);
float f = float((int(animtime*(spd / 7.0f))) % animspd) / float(animspd);
return vec2(f * fdx, f * fdy);
}
void main()
{
vec4 normal_pos = texelFetch(heightmap, ivec2(gl_VertexID, gl_InstanceID), 0);
vec3 pos_base = instances[gl_InstanceID].ChunkXYZBase_Pad1.xyz;
instanceID = base_instance + gl_InstanceID;
vec4 normal_pos = texelFetch(heightmap, ivec2(gl_VertexID, instanceID), 0);
vec3 pos_base = instances[instanceID].ChunkXYZBase_Pad1.xyz;
vec3 pos = vec3(position.x + pos_base.x, pos_base.y + normal_pos.a, position.y + pos_base.z);
bool is_hole = isHoleVertex(gl_VertexID, instances[gl_InstanceID].ChunkHoles_DrawImpass_TexLayerCount_CantPaint.r);
bool is_hole = isHoleVertex(gl_VertexID, instances[instanceID].ChunkHoles_DrawImpass_TexLayerCount_CantPaint.r);
float NaN = makeNaN(1);
@@ -102,8 +121,20 @@ void main()
vary_normal = normal_pos.rgb;
vary_position = pos;
vary_mccv = texelFetch(mccv, ivec2(gl_VertexID, instanceID), 0).rgb;
vary_t0_uv = texcoord + animUVOffset(instances[instanceID].ChunkTexDoAnim.r,
instances[instanceID].ChunkTexAnimSpeed.r, instances[instanceID].ChunkTexAnimDir.r);
vary_t1_uv = texcoord + animUVOffset(instances[instanceID].ChunkTexDoAnim.g,
instances[instanceID].ChunkTexAnimSpeed.g, instances[instanceID].ChunkTexAnimDir.g);
vary_t2_uv = texcoord + animUVOffset(instances[instanceID].ChunkTexDoAnim.b,
instances[instanceID].ChunkTexAnimSpeed.b, instances[instanceID].ChunkTexAnimDir.b);
vary_t3_uv = texcoord + animUVOffset(instances[instanceID].ChunkTexDoAnim.a,
instances[instanceID].ChunkTexAnimSpeed.a, instances[instanceID].ChunkTexAnimDir.a);
vary_texcoord = texcoord;
vary_mccv = texelFetch(mccv, ivec2(gl_VertexID, gl_InstanceID), 0).rgb;
instanceID = gl_InstanceID;
}

View File

@@ -32,6 +32,13 @@ namespace math
, z (z_)
{}
template<typename U>
explicit vector_3d_base<T> (vector_3d_base<U> const& other)
: x (other.x)
, y (other.y)
, z (other.z)
{}
inline static vector_3d_base<T> min()
{
return {std::numeric_limits<T>::lowest(), std::numeric_limits<T>::lowest(), std::numeric_limits<T>::lowest()};

View File

@@ -79,6 +79,7 @@ public:
std::unique_ptr<TextureSet> texture_set;
int holes;
bool currently_paintable = true;
unsigned int areaID;
@@ -128,6 +129,8 @@ public:
ChunkWater* liquid_chunk() const;
bool hasColors() const { return hasMCCV; };
void updateVerticesData();
void recalcNorms();
void updateNormalsData();

View File

@@ -150,6 +150,20 @@ struct MCCV
uint32_t effectID;
};
struct MCLYFlags
{
uint32_t animation_rotation : 3; // each tick is 45°
uint32_t animation_speed : 3;
uint32_t animation_enabled : 1;
uint32_t overbright : 1; // This will make the texture way brighter. Used for lava to make it "glow".
uint32_t use_alpha_map : 1; // set for every layer after the first
uint32_t alpha_map_compressed : 1; // see MCAL chunk description
uint32_t use_cube_map_reflection : 1; // This makes the layer behave like its a reflection of the skybox. See below
uint32_t unknown_0x800 : 1; // WoD?+ if either of 0x800 or 0x1000 is set, texture effects' texture_scale is applied
uint32_t unknown_0x1000 : 1; // WoD?+ see 0x800
uint32_t : 19;
};
struct ENTRY_MCLY
{
uint32_t textureID;

View File

@@ -12,6 +12,7 @@
#include <noggit/alphamap.hpp>
#include <noggit/map_index.hpp>
#include <noggit/texture_set.hpp>
#include <noggit/ui/TexturingGUI.h>
#include <opengl/scoped.hpp>
#include <opengl/shader.hpp>
#include <external/tracy/Tracy.hpp>
@@ -27,6 +28,7 @@
#include <vector>
#include <limits>
MapTile::MapTile( int pX
, int pZ
, std::string const& pFilename
@@ -321,10 +323,11 @@ void MapTile::finishLoading()
auto& chunk_render_instance = _chunk_instance_data[nextChunk];
chunk_render_instance.ChunkHoles_DrawImpass_TexLayerCount_CantPaint[0] = chunk->holes;
chunk_render_instance.ChunkHoles_DrawImpass_TexLayerCount_CantPaint[1] = 0;
chunk_render_instance.ChunkHoles_DrawImpass_TexLayerCount_CantPaint[1] = chunk->header_flags.flags.impass;
chunk_render_instance.ChunkHoles_DrawImpass_TexLayerCount_CantPaint[2] = chunk->texture_set->num();
chunk_render_instance.ChunkHoles_DrawImpass_TexLayerCount_CantPaint[3] = 0;
chunk_render_instance.AreaIDColor_DrawSelection[3] = 0;
chunk_render_instance.AreaIDColor_Pad2_DrawSelection[0] = chunk->areaID;
chunk_render_instance.AreaIDColor_Pad2_DrawSelection[3] = 0;
}
theFile.close();
@@ -392,17 +395,21 @@ void MapTile::draw ( math::frustum const& frustum
, std::map<int, misc::random_color>& area_id_colors
, int animtime
, display_mode display
, std::array<int, 4>& textures_bound
, bool is_selected
)
{
ZoneScopedN("MapTile::draw()");
ZoneScopedN(BOOST_CURRENT_FUNCTION);
static constexpr unsigned NUM_SAMPLERS = 11;
if (!finished)
[[unlikely]]
{
return;
}
if (!_uploaded)
[[unlikely]]
{
uploadTextures();
_buffers.upload();
@@ -429,21 +436,56 @@ void MapTile::draw ( math::frustum const& frustum
bool mccv_bound = false;
bool texture_not_loaded = false;
if (_chunk_update_flags)
// figure out if we need to update based on paintability
bool need_paintability_update = false;
if (draw_paintability_overlay && show_unpaintable_chunks)
[[unlikely]]
{
for (int j = 0; j < 16; ++j)
{
for (int i = 0; i < 16; ++i)
{
auto& chunk = mChunks[j][i];
_chunk_instance_data[i * 16 + j].pad1 = {chunk->xbase, chunk->ybase, chunk->zbase, 1.0};
auto cur_tex = noggit::ui::selected_texture::get();
bool cant_paint = cur_tex && !chunk->canPaintTexture(*cur_tex);
if (chunk->currently_paintable != !cant_paint)
{
chunk->currently_paintable = !cant_paint;
_chunk_instance_data[i * 16 + j].ChunkHoles_DrawImpass_TexLayerCount_CantPaint[3] = cant_paint;
need_paintability_update = true;
}
}
}
}
// run chunk updates. running this when splitdraw call detected unused sampler configuration as well.
if (_chunk_update_flags || is_selected != _selected || need_paintability_update || _requires_sampler_reset)
{
// get back to initial vector size if sampler reset is needed.
if (_requires_sampler_reset)
[[unlikely]]
{
_samplers = std::vector{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
_split_drawcall = false;
}
_selected = is_selected;
for (int j = 0; j < 16; ++j)
{
for (int i = 0; i < 16; ++i)
{
auto& chunk = mChunks[j][i];
_chunk_instance_data[i * 16 + j].ChunkXYZBase_Pad1 = {chunk->xbase, chunk->ybase, chunk->zbase, 1.0};
unsigned flags = chunk->getUpdateFlags();
if (!flags)
continue;
if (flags & ChunkUpdateFlags::ALPHAMAP)
if (flags & ChunkUpdateFlags::ALPHAMAP || _requires_sampler_reset)
{
gl.activeTexture(GL_TEXTURE0 + 3);
gl.bindTexture(GL_TEXTURE_2D_ARRAY, _alphamap_tex);
@@ -468,22 +510,34 @@ void MapTile::draw ( math::frustum const& frustum
int tex_index = (*chunk->texture_set->getTextures())[k]->array_index();
int sampler_id = -1;
for (int n = 0; n < 11; ++n)
for (int n = 0; n < _samplers.size(); ++n)
{
if (_samplers[n] == tex_array)
{
sampler_id = n;
sampler_id = n % NUM_SAMPLERS;
break;
}
else if (_samplers[n] < 0)
{
_samplers[n] = tex_array;
sampler_id = n;
sampler_id = n % NUM_SAMPLERS;
break;
}
}
// If there are not enough sampler slots (11) we have to split the drawcall :(.
// Extremely infrequent for terrain. Never for Blizzard terrain as their tilesets
// use uniform BLP format per map.
if (sampler_id < 0)
throw std::logic_error("Not enough allowed texture units! :(");
[[unlikely]]
{
_split_drawcall = true;
unsigned old_size = _samplers.size();
_samplers.resize(old_size * 2);
std::fill(_samplers.begin() + old_size, _samplers.end(), -1);
_samplers[old_size] = tex_array;
sampler_id = old_size % NUM_SAMPLERS;
}
_chunk_instance_data[i * 16 + j].ChunkTextureSamplers[k] = sampler_id;
_chunk_instance_data[i * 16 + j].ChunkTextureArrayIDs[k] = tex_index;
@@ -519,28 +573,61 @@ void MapTile::draw ( math::frustum const& frustum
chunk->update_shadows();
}
if (flags & ChunkUpdateFlags::HOLES)
{
_chunk_instance_data[i * 16 + j].ChunkHoles_DrawImpass_TexLayerCount_CantPaint[0] = chunk->holes;
}
if (!texture_not_loaded)
chunk->endChunkUpdates();
if (flags & ChunkUpdateFlags::FLAGS)
{
_chunk_instance_data[i * 16 + j].ChunkHoles_DrawImpass_TexLayerCount_CantPaint[1] = chunk->header_flags.flags.impass;
for (int k = 0; k < chunk->texture_set->num(); ++k)
{
unsigned layer_flags = chunk->texture_set->flag(k);
auto flag_view = reinterpret_cast<MCLYFlags*>(&layer_flags);
_chunk_instance_data[i * 16 + j].ChunkTexDoAnim[k] = flag_view->animation_enabled;
_chunk_instance_data[i * 16 + j].ChunkTexAnimSpeed[k] = flag_view->animation_speed;
_chunk_instance_data[i * 16 + j].ChunkTexAnimDir[k] = flag_view->animation_rotation;
}
_chunk_instance_data[i * 16 + j].ChunkTexDoAnim[1] = chunk->header_flags.flags.impass;
}
if (flags & ChunkUpdateFlags::AREA_ID)
{
_chunk_instance_data[i * 16 + j].AreaIDColor_Pad2_DrawSelection[0] = chunk->areaID;
}
_chunk_instance_data[i * 16 + j].AreaIDColor_Pad2_DrawSelection[3] = _selected;
chunk->endChunkUpdates();
if (texture_not_loaded)
chunk->registerChunkUpdate(ChunkUpdateFlags::ALPHAMAP);
_chunk_instance_data[i * 16 + j].ChunkHoles_DrawImpass_TexLayerCount_CantPaint[1] = 0;
_chunk_instance_data[i * 16 + j].ChunkHoles_DrawImpass_TexLayerCount_CantPaint[3] = 0;
_chunk_instance_data[i * 16 + j].AreaIDColor_DrawSelection[3] = 0;
}
_requires_sampler_reset = false;
}
if (!texture_not_loaded)
endChunkUpdates();
endChunkUpdates();
if (texture_not_loaded)
registerChunkUpdate(ChunkUpdateFlags::ALPHAMAP);
gl.bufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(opengl::ChunkInstanceDataUniformBlock) * 256, &_chunk_instance_data);
}
// do not draw anything when textures did not finish loading
if (texture_not_loaded)
[[unlikely]]
{
return;
}
if (!alphamap_bound)
{
gl.activeTexture(GL_TEXTURE0 + 3);
@@ -565,20 +652,109 @@ void MapTile::draw ( math::frustum const& frustum
gl.bindTexture(GL_TEXTURE_2D, _height_tex);
}
for (int i = 0; i < 11; ++i)
if (!_split_drawcall)
[[likely]]
{
gl.activeTexture(GL_TEXTURE0 + 5 + i);
if (_samplers[i] < 0)
for (int i = 0; i < NUM_SAMPLERS; ++i)
{
gl.bindTexture(GL_TEXTURE_2D_ARRAY, 0);
continue;
gl.activeTexture(GL_TEXTURE0 + 5 + i);
if (_samplers[i] < 0)
{
gl.bindTexture(GL_TEXTURE_2D_ARRAY, 0);
continue;
}
gl.bindTexture(GL_TEXTURE_2D_ARRAY, _samplers[i]);
}
gl.bindTexture(GL_TEXTURE_2D_ARRAY, _samplers[i]);
gl.drawElementsInstanced(GL_TRIANGLES, 768, GL_UNSIGNED_SHORT, nullptr, 256);
}
else
[[unlikely]]
{
std::array<int, NUM_SAMPLERS> batch_samplers{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
gl.drawElementsInstanced(GL_TRIANGLES, 768, GL_UNSIGNED_SHORT, nullptr, 256);
bool even_sampler_sets = !(_samplers.size() % NUM_SAMPLERS);
unsigned n_sampler_sets = even_sampler_sets ? _samplers.size() / NUM_SAMPLERS : _samplers.size() / NUM_SAMPLERS + 1;
unsigned cur_sampler_set = 0;
unsigned chunk_index_start = 0;
unsigned n_chunks = 0;
while (cur_sampler_set < n_sampler_sets)
{
std::fill(batch_samplers.begin(), batch_samplers.end(), -1);
n_chunks = 0;
// find out the number of chunks we can draw with current samplers
for (int j = chunk_index_start / 16; j < 16; ++j)
{
for (int i = chunk_index_start % 16; i < 16; ++i)
{
auto& chunk = mChunks[j][i];
auto& chunk_textures = (*chunk->texture_set->getTextures());
for (int k = 0; k < chunk->texture_set->num(); ++k)
{
GLuint tex_array = (*chunk->texture_set->getTextures())[k]->texture_array();
int tex_index = (*chunk->texture_set->getTextures())[k]->array_index();
int sampler_id = -1;
for (int n = 0; n < NUM_SAMPLERS; ++n)
{
if (batch_samplers[n] == tex_array)
{
sampler_id = n;
break;
}
else if (batch_samplers[n] < 0)
{
batch_samplers[n] = tex_array;
sampler_id = n;
break;
}
}
if (sampler_id < 0)
{
chunk_index_start = i * 16 + j;
goto MapTile_DrawSplitDrawCallBreak;
}
}
n_chunks++;
}
}
MapTile_DrawSplitDrawCallBreak:
// perform split drawcall
for (int i = 0; i < NUM_SAMPLERS; ++i)
{
gl.activeTexture(GL_TEXTURE0 + 5 + i);
if (batch_samplers[i] < 0)
{
gl.bindTexture(GL_TEXTURE_2D_ARRAY, 0);
continue;
}
gl.bindTexture(GL_TEXTURE_2D_ARRAY, batch_samplers[i]);
}
mcnk_shader.uniform("base_instance", static_cast<int>(chunk_index_start));
gl.drawElementsInstanced(GL_TRIANGLES, 768, GL_UNSIGNED_SHORT, nullptr, n_chunks);
cur_sampler_set++;
if (!n_chunks)
{
_requires_sampler_reset = true;
}
}
mcnk_shader.uniform("base_instance", 0);
}
}

View File

@@ -88,7 +88,7 @@ public:
, std::map<int, misc::random_color>& area_id_colors
, int animtime
, display_mode display
, std::array<int, 4>& textures_bound
, bool is_selected
);
bool intersect (math::ray const&, selection_result*) const;
void drawWater ( math::frustum const& frustum
@@ -158,6 +158,9 @@ private:
tile_mode _mode;
bool _tile_is_being_reloaded;
bool _uploaded = false;
bool _selected = false;
bool _split_drawcall = false;
bool _requires_sampler_reset = true;
// MFBO:
math::vector_3d mMinimumValues[3 * 3];

View File

@@ -48,6 +48,8 @@
#include <opengl/types.hpp>
#include <limits>
#include <noggit/scripting/scripting_tool.hpp>
#include <noggit/scripting/script_settings.hpp>
#include <noggit/ActionManager.hpp>
#include <noggit/Action.hpp>
@@ -742,6 +744,13 @@ void MapView::setupVertexPainterUi()
shaderTool = new noggit::ui::shader_tool(this, this);
_tool_panel_dock->registerTool("Vertex Painter", shaderTool);
}
void MapView::setupScriptingUi()
{
scriptingTool = new noggit::scripting::scripting_tool(this, this, _settings);
_tool_panel_dock->registerTool("Scripting", scriptingTool);
}
void MapView::setupObjectEditorUi()
{
/* Tool */
@@ -2362,10 +2371,11 @@ void MapView::createGUI()
setupObjectEditorUi();
setupMinimapEditorUi();
setupStampUi();
setupLightEditorUi();
setupScriptingUi();
// End combined dock
setupViewportOverlay();
setupLightEditorUi();
setupNodeEditor();
setupAssetBrowser();
setupDetailInfos();
@@ -3215,6 +3225,11 @@ void MapView::tick (float dt)
for (auto& selection : currentSelection)
{
if (selection.which() == eEntry_MapChunk && terrainMode == editing_mode::scripting)
{
scriptingTool->sendBrushEvent(_cursor_pos, 7.5f * dt);
}
if (leftMouse && selection.which() == eEntry_MapChunk)
{
bool underMap = _world->isUnderMap(_cursor_pos);
@@ -4039,6 +4054,10 @@ void MapView::draw_map()
case editing_mode::minimap:
radius = minimapTool->brushRadius();
break;
case editing_mode::scripting:
radius = scriptingTool->get_settings()->brushRadius();
inner_radius = scriptingTool->get_settings()->innerRadius();
break;
default:
break;
}

View File

@@ -62,6 +62,10 @@ namespace noggit
class LightEditor;
}
namespace scripting
{
class scripting_tool;
}
class camera;
namespace ui
@@ -95,13 +99,22 @@ enum class save_mode
class MapView : public noggit::Red::ViewportManager::Viewport
{
Q_OBJECT
private:
public:
bool _mod_alt_down = false;
bool _mod_ctrl_down = false;
bool _mod_shift_down = false;
bool _mod_space_down = false;
bool _mod_num_down = false;
bool leftMouse = false;
bool leftClicked = false;
bool rightMouse = false;
std::unique_ptr<World> _world;
noggit::camera _camera;
private:
float _2d_zoom = 1.f;
float moving, strafing, updown, mousedir, turn, lookat;
CursorType _cursorType;
@@ -110,7 +123,6 @@ private:
bool look, freelook;
bool ui_hidden = false;
noggit::camera _camera;
bool _camera_moved_since_last_draw = true;
public:
@@ -172,10 +184,6 @@ private:
bool _rotation_editor_need_update = false;
bool leftMouse = false;
bool leftClicked = false;
bool rightMouse = false;
bool mmap_render_success = false;
int mmap_render_index = 0;
@@ -313,8 +321,6 @@ private:
math::vector_4d normalized_device_coords (int x, int y) const;
float aspect_ratio() const;
std::unique_ptr<World> _world;
noggit::TabletManager* _tablet_manager;
QLabel* _status_position;
@@ -372,6 +378,7 @@ private:
noggit::ui::MinimapCreator* minimapTool;
noggit::Red::BrushStack* stampTool;
noggit::Red::LightEditor* lightEditor;
noggit::scripting::scripting_tool* scriptingTool;
opengl::texture* const _texBrush;
@@ -413,6 +420,7 @@ private:
void setupMinimapEditorUi();
void setupStampUi();
void setupLightEditorUi();
void setupScriptingUi();
void setupNodeEditor();
void setupAssetBrowser();
void setupDetailInfos();

View File

@@ -775,6 +775,16 @@ void World::initDisplay()
ol = std::make_unique<OutdoorLighting> ("World\\dnc.db");
}
MapChunk* World::getChunkAt(math::vector_3d const& pos)
{
MapTile* tile(mapIndex.getTile(pos));
if (tile && tile->finishedLoading())
{
return tile->getChunk((pos.x - tile->xbase) / CHUNKSIZE, (pos.z - tile->zbase) / CHUNKSIZE);
}
return nullptr;
}
void World::initShaders()
{
if (!_display_initialized)
@@ -915,6 +925,7 @@ void World::initShaders()
mcnk_shader.uniform("shadowmap", 2);
mcnk_shader.uniform("alphamap", 3);
mcnk_shader.uniform("stamp_brush", 4);
mcnk_shader.uniform("base_instance", 0);
std::vector<int> samplers {5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
mcnk_shader.uniform("textures", samplers);
@@ -1092,6 +1103,7 @@ void World::draw ( math::matrix_4x4 const& model_view
opengl::scoped::use_program mcnk_shader{ *_mcnk_program.get() };
mcnk_shader.uniform ("camera", camera_pos);
mcnk_shader.uniform ("animtime", static_cast<int>(animtime));
if (cursor_type != CursorType::NONE)
{
@@ -1108,25 +1120,13 @@ void World::draw ( math::matrix_4x4 const& model_view
}
std::array<int, 4> textures_bound = { -1, -1, -1, -1 };
//std::array<int, 4> textures_bound = { -1, -1, -1, -1 };
for (MapTile* tile : mapIndex.loaded_tiles())
{
if (terrainMode == editing_mode::minimap
&& minimap_render_settings->selected_tiles.at(64 * tile->index.x + tile->index.z))
{
//mcnk_shader.uniform("draw_selection", 1);
}
else
{
// mcnk_shader.uniform("draw_selection", 0);
}
gl.bindVertexArray(_mapchunk_vao);
gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, _mapchunk_index);
tile->draw ( frustum
, mcnk_shader
, culldistance
@@ -1139,7 +1139,8 @@ void World::draw ( math::matrix_4x4 const& model_view
, area_id_colors
, animtime
, display
, textures_bound
, terrainMode == editing_mode::minimap
&& minimap_render_settings->selected_tiles.at(64 * tile->index.x + tile->index.z)
);
}
@@ -2720,6 +2721,13 @@ void World::reload_tile(tile_index const& tile)
mapIndex.reloadTile(tile);
}
void World::deleteObjects(std::vector<selection_type> const& types)
{
ZoneScoped;
_model_instance_storage.delete_instances(types);
need_model_updates = true;
}
void World::updateTilesEntry(selection_type const& entry, model_update type)
{
ZoneScoped;
@@ -2735,6 +2743,17 @@ void World::updateTilesEntry(selection_type const& entry, model_update type)
}
void World::updateTilesEntry(SceneObject* entry, model_update type)
{
ZoneScoped;
if (entry->which() == eWMO)
updateTilesWMO (static_cast<WMOInstance*>(entry), type);
else if (entry->which() == eMODEL)
updateTilesModel (static_cast<ModelInstance*>(entry), type);
}
void World::updateTilesWMO(WMOInstance* wmo, model_update type)
{
ZoneScoped;

View File

@@ -150,6 +150,8 @@ public:
, bool draw_hidden_models
);
MapChunk* getChunkAt(math::vector_3d const& pos);
private:
// Information about the currently selected model / WMO / triangle.
int _selected_model_count = 0;
@@ -176,6 +178,7 @@ public:
void reset_selection();
void delete_selected_models();
void range_add_to_selection(math::vector_3d const& pos, float radius, bool remove);
noggit::world_model_instances_storage& getModelInstanceStorage() { return _model_instance_storage; };
enum class m2_scaling_type
{
@@ -328,6 +331,7 @@ public:
void reload_tile(tile_index const& tile);
void updateTilesEntry(selection_type const& entry, model_update type);
void updateTilesEntry(SceneObject* entry, model_update type);
void updateTilesWMO(WMOInstance* wmo, model_update type);
void updateTilesModel(ModelInstance* m2, model_update type);
void wait_for_all_tile_updates();
@@ -378,7 +382,6 @@ public:
bool deselectVertices(math::vector_3d const& pos, float radius);
void selectVertices(math::vector_3d const& pos, float radius);
void moveVertices(float h);
void orientVertices ( math::vector_3d const& ref_pos
, math::degrees vertex_angle
@@ -390,6 +393,8 @@ public:
void updateVertexCenter();
void clearVertexSelection();
void deleteObjects(std::vector<selection_type> const& types);
float getMaxTileHeight(const tile_index& tile);
math::vector_3d const& vertexCenter();

View File

@@ -0,0 +1,183 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#include <noggit/scripting/script_brush.hpp>
#include <noggit/scripting/scripting_tool.hpp>
#include <noggit/scripting/script_settings.hpp>
#include <noggit/scripting/script_profiles.hpp>
#include <noggit/scripting/script_context.hpp>
#include <string>
#include <map>
namespace noggit {
namespace scripting {
script_brush_event::script_brush_event(
script_settings * settings
, math::vector_3d const& pos
, float dt)
: _settings(settings)
, _pos(pos)
, _dt(dt)
{}
math::vector_3d script_brush_event::pos()
{
return _pos;
}
float script_brush_event::outer_radius()
{
return _settings->brushRadius();
}
float script_brush_event::inner_radius()
{
return _settings->innerRadius();
}
void script_brush_event::set_outer_radius(float radius)
{
_settings->setOuterRadius(radius);
}
void script_brush_event::set_inner_radius(float radius)
{
_settings->setInnerRadius(radius);
}
float script_brush_event::dt()
{
return _dt;
}
script_brush::script_brush(
script_context * state
, std::string const& name)
: script_object(state)
, _name(name)
{};
void script_brush::set_name(std::string const& name)
{
_name = name;
}
std::string script_brush::get_name()
{
return _name;
}
std::shared_ptr<int_tag> script_brush::add_int_tag(
std::string const& item
, int low
, int high
, int def
, bool has_slider
){
auto tag = std::make_shared<int_tag>(state(), _name, item, low, high, def, has_slider);
_tags.push_back(tag);
return tag;
}
void script_brush::add_null_tag()
{
add_description("");
}
void script_brush::add_description(std::string const& text)
{
_tags.push_back(std::make_shared<null_tag>(state(),_name,"__null"+std::to_string(_tags.size()),text));
}
std::shared_ptr<real_tag> script_brush::add_real_tag(
std::string const& item
, double low
, double high
, double def
, int zeros
, bool has_slider
){
auto tag = std::make_shared<real_tag>(state(), _name, item, low, high, def, zeros, has_slider);
_tags.push_back(tag);
return tag;
}
std::shared_ptr<string_tag> script_brush::add_string_tag(
std::string const& item
, std::string const& def)
{
auto tag = std::make_shared<string_tag>(state(),_name, item, def);
_tags.push_back(tag);
return tag;
}
std::shared_ptr<string_list_tag> script_brush::add_string_list_tag(
std::string const& item
, sol::variadic_args va)
{
std::vector<std::string> vec;
for(auto v : va)
{
vec.push_back(v);
}
auto tag = std::make_shared<string_list_tag>(state(),_name, item, vec);
_tags.push_back(tag);
return tag;
}
std::shared_ptr<bool_tag> script_brush::add_bool_tag(
std::string const& item
, bool def
) {
auto tag = std::make_shared<bool_tag>(state(),_name,item,def);
_tags.push_back(tag);
return tag;
}
void script_brush::on_selected()
{
for(auto tag : _tags)
{
tag->add_to_settings();
}
}
void register_script_brush(script_context * state)
{
state->new_usertype<script_brush_event>("script_brush_event"
,"pos",&script_brush_event::pos
,"set_outer_radius",&script_brush_event::set_outer_radius
,"set_inner_radius",&script_brush_event::set_inner_radius
,"outer_radius",&script_brush_event::outer_radius
,"inner_radius",&script_brush_event::inner_radius
,"dt",&script_brush_event::dt
);
state->new_usertype<script_brush>("script_brush"
, sol::meta_function::new_index, &script_brush::set
, sol::meta_function::index, &script_brush::get
,"get_name",&script_brush::get_name
,"add_int_tag",sol::overload(
&script_brush::add_int_tag
, &script_brush::add_int_tag_1
, &script_brush::add_int_tag_2
)
,"add_bool_tag",sol::overload(
&script_brush::add_bool_tag
, &script_brush::add_bool_tag_1
)
,"add_real_tag", sol::overload(
&script_brush::add_real_tag
, &script_brush::add_real_tag_1
, &script_brush::add_real_tag_2
)
,"add_string_tag", sol::overload(
&script_brush::add_string_tag
, &script_brush::add_string_tag_1
)
,"add_string_list_tag",&script_brush::add_string_list_tag
,"add_null_tag",&script_brush::add_null_tag
,"add_description",&script_brush::add_description
);
}
}
}

View File

@@ -0,0 +1,144 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#pragma once
#include <noggit/scripting/script_object.hpp>
#include <math/vector_3d.hpp>
#include <sol/sol.hpp>
#include <string>
#include <memory>
namespace noggit {
namespace scripting {
class scripting_tool;
class script_settings;
class bool_tag;
class int_tag;
class real_tag;
class string_tag;
class string_list_tag;
class tag;
class script_context;
enum class brush_event_type
{
CLICK,
HOLD,
RELEASE
};
class script_brush_event
{
public:
script_brush_event( script_settings * settings
, math::vector_3d const& pos
, float dt);
math::vector_3d pos();
float outer_radius();
float inner_radius();
void set_outer_radius(float radius);
void set_inner_radius(float radius);
float dt();
private:
script_settings * _settings;
math::vector_3d _pos;
float _dt;
};
class script_brush: public script_object {
public:
script_brush(script_context * state, std::string const& name);
void set_name(std::string const& name);
std::string get_name();
void on_selected();
std::shared_ptr<int_tag> add_int_tag(
std::string const& item
, int low
, int high
, int def /* = low */
, bool has_slider /* = false */
);
std::shared_ptr<int_tag> add_int_tag_1(
std::string const& item
, int low
, int high
, int def
) { return add_int_tag(item,low,high,def, false);}
std::shared_ptr<int_tag> add_int_tag_2(
std::string const& item
, int low
, int high
) { return add_int_tag_1(item,low,high,low);}
std::shared_ptr<real_tag> add_real_tag(
std::string const& item
, double low
, double high
, double def
, int zeros /* = 5 */
, bool has_slider /* = false */
);
std::shared_ptr<real_tag> add_real_tag_1(
std::string const& item
, double low
, double high
, double def
, int zeros
)
{ return add_real_tag(item,low,high,def,zeros, false); }
std::shared_ptr<real_tag> add_real_tag_2(
std::string const& item
, double low
, double high
, double def
)
{ return add_real_tag_1(item,low,high,def,5); }
std::shared_ptr<string_tag> add_string_tag(
std::string const& item
, std::string const& def /* = "" */
);
std::shared_ptr<string_tag> add_string_tag_1(
std::string const& item)
{ return add_string_tag(item,"");}
std::shared_ptr<string_list_tag> add_string_list_tag(
std::string const& item
, sol::variadic_args va);
std::shared_ptr<bool_tag> add_bool_tag(
std::string const& item
, bool def /* = false */
);
std::shared_ptr<bool_tag> add_bool_tag_1(
std::string const& item
) { return add_bool_tag(item,false); }
void add_null_tag();
void add_description(std::string const& text);
LUA_MEMBER_FUNC(
script_brush,std::shared_ptr<script_brush_event>,on_left_click);
LUA_MEMBER_FUNC(
script_brush,std::shared_ptr<script_brush_event>,on_left_hold);
LUA_MEMBER_FUNC(
script_brush,std::shared_ptr<script_brush_event>,on_left_release);
LUA_MEMBER_FUNC(
script_brush,std::shared_ptr<script_brush_event>,on_right_click);
LUA_MEMBER_FUNC(
script_brush,std::shared_ptr<script_brush_event>,on_right_hold);
LUA_MEMBER_FUNC(
script_brush,std::shared_ptr<script_brush_event>,on_right_release);
private:
std::vector<std::shared_ptr<tag>> _tags;
std::string _name;
};
void register_script_brush(script_context * state);
}
}

View File

@@ -0,0 +1,192 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#include <noggit/scripting/script_chunk.hpp>
#include <noggit/scripting/script_selection.hpp>
#include <noggit/scripting/script_context.hpp>
#include <noggit/scripting/script_exception.hpp>
#include <noggit/scripting/script_vert.hpp>
#include <noggit/scripting/script_tex.hpp>
#include <noggit/scripting/scripting_tool.hpp>
#include <noggit/MapChunk.h>
#include <noggit/MapHeaders.h>
#include <noggit/MapView.h>
#include <noggit/World.h>
#include <noggit/ContextObject.hpp>
#include <boost/algorithm/string/predicate.hpp>
namespace noggit
{
namespace scripting
{
chunk::chunk(script_context * ctx, MapChunk* chunk)
: script_object(ctx)
, _chunk(chunk)
{}
void chunk::set_hole(bool hole)
{
_chunk->setHole(math::vector_3d(0, 0, 0), 10.f, true, hole); // todo: fake const
_chunk->registerChunkUpdate(ChunkUpdateFlags::HOLES);
}
int chunk::add_texture(std::string const& texture, int effectID)
{
std::string tex = std::string(texture);
int tex_index = _chunk->texture_set->addTexture(scoped_blp_texture_reference(tex, noggit::NoggitRenderContext::MAP_VIEW));
if (effectID >= -1)
{
set_effect(tex_index, effectID);
_chunk->texture_set->setEffect(tex_index, effectID);
}
return tex_index;
}
int chunk::get_effect(int index)
{
return _chunk->texture_set->effect(index);
}
void chunk::set_effect(int index, int value)
{
_chunk->texture_set->setEffect(index, value);
_chunk->texture_set->lod_texture_map();
_chunk->registerChunkUpdate(ChunkUpdateFlags::FLAGS);
}
void chunk::clear_textures()
{
_chunk->texture_set->eraseTextures();
}
void chunk::remove_texture(int index)
{
if(index<0||index>3)
{
throw script_exception(
"chunk_remove_texture",
"invalid texture index, must be between 0-3");
}
_chunk->texture_set->eraseTexture(index);
}
int chunk::get_texture_count()
{
return _chunk->texture_set->num();
}
std::string chunk::get_texture(int index)
{
if(index<0||index>3)
{
throw script_exception(
"chunk_get_texture",
"invalid texture index, must be between 0-3");
}
if (_chunk->texture_set->num() <= index)
{
throw script_exception(
"chunk_get_texture",
"texture index out of range"
);
}
return _chunk->texture_set->texture(index)->filename;
}
void chunk::apply_heightmap()
{
_chunk->registerChunkUpdate(ChunkUpdateFlags::VERTEX | ChunkUpdateFlags::NORMALS);
world()->recalc_norms(_chunk);
}
void chunk::apply_textures()
{
_chunk->registerChunkUpdate(ChunkUpdateFlags::ALPHAMAP);
}
void chunk::apply_vertex_color()
{
_chunk->registerChunkUpdate(ChunkUpdateFlags::MCCV);
}
void chunk::apply_all()
{
apply_heightmap();
apply_textures();
apply_vertex_color();
}
int chunk::get_area_id()
{
return _chunk->getAreaID();
}
void chunk::set_area_id(int value)
{
return _chunk->setAreaID(value);
}
void chunk::set_impassable(bool add)
{
_chunk->setFlag(add, 0x2);
}
void chunk::clear_colors()
{
std::fill (
_chunk->mccv,
_chunk->mccv + mapbufsize,
math::vector_3d (1.f, 1.f, 1.f)
);
}
tex chunk::get_tex(int index)
{
return tex(state(),_chunk,index);
}
vert chunk::get_vert(int index)
{
return vert(state(), _chunk, index);
}
std::shared_ptr<selection> chunk::to_selection()
{
return std::make_shared<selection>(state(), "chunk#to_selection", _chunk->vmin,_chunk->vmax);
}
void register_chunk(script_context * state)
{
state->set_function("get_chunk", [state](math::vector_3d const& pos) {
return chunk(state,state->tool()->get_view()->_world->getChunkAt(pos));
});
state->new_usertype<chunk>("chunk"
, "remove_texture", &chunk::remove_texture
, "get_texture_count", &chunk::get_texture_count
, "get_texture", &chunk::get_texture
, "get_effect", &chunk::get_effect
, "set_effect", &chunk::set_effect
, "add_texture", sol::overload(
&chunk::add_texture
, &chunk::add_texture_1
)
, "clear_textures", &chunk::clear_textures
, "set_hole", &chunk::set_hole
, "clear_colors", &chunk::clear_colors
, "apply_textures", &chunk::apply_textures
, "apply_heightmap", &chunk::apply_heightmap
, "apply_vertex_color", &chunk::apply_vertex_color
, "apply_all", &chunk::apply_all
, "apply", &chunk::apply_all
, "set_impassable", &chunk::set_impassable
, "get_area_id", &chunk::get_area_id
, "set_area_id", &chunk::set_area_id
, "to_selection", &chunk::to_selection
, "get_tex", &chunk::get_tex
, "get_vert", &chunk::get_vert
);
}
} // namespace scripting
} // namespace noggit

View File

@@ -0,0 +1,48 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#pragma once
#include <noggit/scripting/script_vert.hpp>
#include <noggit/scripting/script_object.hpp>
#include <noggit/MapChunk.h>
namespace noggit
{
namespace scripting
{
class script_context;
class selection;
class tex;
class vert;
class chunk: public script_object
{
public:
chunk(script_context * ctx, MapChunk* chunk);
void remove_texture(int index);
std::string get_texture(int index);
int get_effect(int index);
void set_effect(int index, int effectID);
int add_texture(std::string const& texture, int effectID /* = -2*/);
int add_texture_1(std::string const& texture)
{ return add_texture(texture,-2);}
int get_texture_count();
void clear_textures();
void set_hole(bool hole);
void clear_colors();
void apply_textures();
void apply_heightmap();
void apply_vertex_color();
void apply_all();
void set_impassable(bool add);
int get_area_id();
void set_area_id(int value);
tex get_tex(int index);
vert get_vert(int index);
std::shared_ptr<selection> to_selection();
private:
MapChunk* _chunk;
friend class selection;
};
void register_chunk(script_context * state);
} // namespace scripting
} // namespace noggit

View File

@@ -0,0 +1,188 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#include <noggit/scripting/script_context.hpp>
#include <noggit/scripting/scripting_tool.hpp>
#include <noggit/scripting/script_registry.ipp>
#include <noggit/scripting/script_exception.hpp>
#include <noggit/scripting/script_object.hpp>
#include <noggit/MapView.h>
#include <noggit/World.h>
#include <noggit/camera.hpp>
#include <boost/filesystem.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <noggit/Log.h>
#include <vector>
namespace noggit
{
namespace scripting
{
namespace
{
void set_tool_error(scripting_tool * tool)
{
tool->resetLogScroll();
//tool->setStyleSheet("background-color: #f0a5a5;");
}
}
script_context::script_context(scripting_tool * tool): _tool(tool)
{
open_libraries(sol::lib::base,sol::lib::table,sol::lib::string);
script_scoped_function<std::shared_ptr<script_brush>(std::string const&)>
add_brush(this,"brush",
[this](std::string const& name)
{
auto brush = std::make_shared<script_brush>(this, name);
this->get_scripts().push_back(brush);
return brush;
});
set_function("require", [this](std::string const& name) {
return this->require(name);
});
register_functions(this);
boost::filesystem::recursive_directory_iterator end;
if(!boost::filesystem::exists("scripts"))
{
_tool->addLog("[error]: 'scripts' directory does not exist");
set_tool_error(_tool);
return;
}
if(!boost::filesystem::is_directory("scripts"))
{
_tool->addLog("[error]: 'scripts' is not a directory");
set_tool_error(_tool);
return;
}
unsigned int error_count = 0;
unsigned int file_count = 0;
for (boost::filesystem::recursive_directory_iterator dir("scripts"); dir != end; ++dir)
{
std::string file = dir->path().string();
if (!boost::ends_with(file, ".lua") || boost::ends_with(file, ".spec.lua"))
{
continue;
}
++file_count;
try
{
execute_file(dir->path().string());
}
catch (std::exception e)
{
++error_count;
std::string what = e.what();
if (what.size() == 0)
{
what = std::string("Generic error in file during initialization (check function names and arguments)");
}
_tool->addLog("[error]: " + what + " (in file "+file+")");
set_tool_error(_tool);
}
}
if(file_count == 0)
{
_tool->addLog("[error]: no script files found (check your 'scripts' directory)");
set_tool_error(_tool);
++error_count;
}
if(error_count == 0)
{
_tool->setStyleSheet("");
}
}
scripting_tool * script_context::tool()
{
return _tool;
}
std::string script_context::get_selected_name()
{
if(_selected == -1)
{
return "";
}
return _scripts[_selected]->get_name();
}
std::vector<std::shared_ptr<script_brush>> & script_context::get_scripts()
{
return _scripts;
}
void script_context::select_script(int index)
{
_selected = index;
auto v = get_scripts()[_selected];
v->on_selected();
}
int script_context::get_selection()
{
return _selected;
}
sol::table script_context::require(std::string const& mod)
{
std::string err_str;
for(auto& val: this->_file_stack)
{
err_str+=val;
if(val==mod)
{
throw script_exception("require","circular dependency: "+err_str);
}
err_str+="->";
}
if(_modules.find(mod)==_modules.end())
{
execute_file(module_to_file(mod));
}
return _modules[mod];
}
World * script_context::world()
{
return _tool->get_view()->_world.get();
}
std::string script_context::file_to_module(std::string const& file)
{
auto rel = boost::filesystem::relative(boost::filesystem::path(file),boost::filesystem::path("scripts"))
.string();
std::replace(rel.begin(),rel.end(),'\\','/');
return rel.substr(0,rel.size()-strlen(".lua"));
}
std::string script_context::module_to_file(std::string const& mod)
{
return (boost::filesystem::path("scripts") / boost::filesystem::path(mod + ".lua")).string();
}
void script_context::execute_file(std::string const& file)
{
auto mod = file_to_module(file);
_file_stack.push_back(mod);
sol::protected_function_result res = script_file(file);
_modules[mod] = res.get_type() == sol::type::table
? res.get<sol::table>()
: create_table();
_file_stack.pop_back();
}
} // namespace scripting
} // namespace noggit

View File

@@ -0,0 +1,66 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#pragma once
#include <noggit/scripting/script_brush.hpp>
#include <sol/sol.hpp>
#include <functional>
#include <map>
#include <set>
class World;
namespace noggit
{
class camera;
namespace scripting
{
class scripting_tool;
class script_context: public sol::state
{
public:
script_context(scripting_tool * tool);
void select_script(int index);
int get_selection();
World * world();
scripting_tool * tool();
std::string get_selected_name();
std::vector<std::shared_ptr<script_brush>> &get_scripts();
sol::table require(std::string const& path);
void execute_file(std::string const& filename);
std::string file_to_module(std::string const& file);
std::string module_to_file(std::string const& module);
private:
scripting_tool * _tool;
std::vector<std::shared_ptr<script_brush>> _scripts;
std::map<std::string, sol::table> _modules;
std::vector<std::string> _file_stack;
int _selected = -1;
};
template <typename T>
class script_scoped_function
{
public:
script_scoped_function( script_context *lua
, std::string const &name
, std::function<T> fun
)
: _lua(lua)
, _name(name)
{
lua->set_function(name, fun);
}
script_scoped_function()
{
_lua->set_function(_name, nullptr);
}
private:
script_context* _lua;
std::string _name;
};
} // namespace scripting
} // namespace noggit

View File

@@ -0,0 +1,21 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#include <noggit/scripting/scripting_tool.hpp>
#include <noggit/scripting/script_exception.hpp>
#include <string>
#include <exception>
namespace noggit
{
namespace scripting
{
script_exception::script_exception(std::string const& funcName, std::string const& msg)
: std::runtime_error(msg+" (in function "+funcName+")")
{
// TEMP: remove when exceptions are working
if(msg.find("C++ exception") != 0)
{
set_cur_exception(std::string(what()));
}
}
} // namespace scripting
} // namespace noggit

View File

@@ -0,0 +1,17 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#pragma once
#include <stdexcept>
#include <string>
namespace noggit
{
namespace scripting
{
class script_exception : public std::runtime_error
{
public:
script_exception(std::string const& funcName, std::string const& msg);
};
} // namespace scripting
} // namespace noggit

View File

@@ -0,0 +1,110 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#include <noggit/scripting/script_exception.hpp>
#include <noggit/scripting/script_filesystem.hpp>
#include <noggit/scripting/scripting_tool.hpp>
#include <noggit/scripting/script_context.hpp>
#include <noggit/ui/SettingsPanel.h>
#include <QtWidgets/QMessageBox>
#include <boost/filesystem.hpp>
#include <sol/sol.hpp>
#include <set>
namespace fs = boost::filesystem;
namespace noggit
{
namespace scripting
{
void mkdirs(std::string const& pathstr)
{
auto path = fs::path(pathstr);
auto parent_path = path.parent_path();
if (parent_path.string().size() > 0)
{
fs::create_directories(path.parent_path());
}
}
std::string read_file(std::string const& path)
{
if (!fs::exists(path))
{
throw script_exception("read_file","no such file:" + std::string (path));
}
std::ifstream t(path);
std::string str((std::istreambuf_iterator<char>(t)),
std::istreambuf_iterator<char>());
return str;
}
namespace {
std::set<boost::filesystem::path> allowed_files;
}
boost::filesystem::path get_writable_path(std::string const& caller, script_context * state, std::string const& path)
{
auto canonical = boost::filesystem::weakly_canonical(boost::filesystem::path(path));
if (state->tool()->get_noggit_settings()->value("allow_scripts_write_any_file", false).toBool())
{
return canonical;
}
if (allowed_files.find(canonical) != allowed_files.end())
{
return canonical;
}
QMessageBox prompt;
prompt.setText(std::string("A script wants to write to the file "+canonical.string()).c_str());
prompt.setInformativeText(std::string("Do you want to allow the script to write to "+canonical.string()+"?").c_str());
prompt.setStandardButtons(QMessageBox::StandardButton::Yes | QMessageBox::StandardButton::No);
prompt.setDefaultButton(QMessageBox::No);
bool answer = prompt.exec() == QMessageBox::StandardButton::Yes;
if(!answer)
{
throw script_exception(caller,"No permission to write file "+canonical.string());
}
return *allowed_files.emplace (canonical).first;
}
void write_file(script_context * ctx, std::string const& path, std::string const& input)
{
auto writable_path = get_writable_path("write_file",ctx,path);
mkdirs(writable_path.string());
std::ofstream(writable_path.string()) << input;
}
void append_file(script_context * ctx, std::string const& path, std::string const& input)
{
auto writable_path = get_writable_path("append_file",ctx,path);
mkdirs(writable_path.string());
std::ofstream outfile;
outfile.open(writable_path.string(), std::ios_base::app); // append instead of overwrite
outfile << input;
}
bool path_exists(std::string const& path)
{
return fs::exists(path);
}
void register_filesystem(script_context * state)
{
state->set_function("write_file", [state](
std::string const& path
, std::string const& input
) {
write_file(state, path, input);
});
state->set_function("append_file", [state](
std::string const& path
, std::string const& input
) {
append_file(state, path, input);
});
state->set_function("read_file",read_file);
state->set_function("path_exists",path_exists);
}
} // namespace scripting
} // namespace noggit

View File

@@ -0,0 +1,23 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#pragma once
#include <boost/filesystem.hpp>
#include <string>
namespace noggit
{
namespace scripting
{
class script_context;
class scripting_tool;
namespace fs = boost::filesystem;
boost::filesystem::path get_writable_path(std::string const& caller, script_context * state, std::string const& path);
void write_file(script_context * ctx, std::string const& path, std::string const& content);
void append_file(script_context * ctx, std::string const& path, std::string const& content);
std::string read_file(std::string const& path);
bool path_exists(std::string const& path);
void register_filesystem(script_context * state);
void mkdirs(std::string const& path);
} // namespace scripting
} // namespace noggit

View File

@@ -0,0 +1,129 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#include <noggit/scripting/scripting_tool.hpp>
#include <noggit/scripting/script_global.hpp>
#include <noggit/MapView.h>
#include <noggit/World.h>
#include <noggit/scripting/script_context.hpp>
#include <noggit/scripting/script_chunk.hpp>
#include <noggit/ui/ObjectEditor.h>
namespace noggit {
namespace scripting {
void register_global(script_context * state)
{
scripting_tool * global = state->tool();
state->set_function("camera_pos",[global]()
{
return global->get_view()->_camera.position;
});
state->set_function("add_m2",[global](
std::string const& filename
, math::vector_3d const& pos
, float scale
, math::vector_3d const& rotation)
{
// note: we set both min/max random scale and the normal scale parameter,
// because noggit picks one based on random scale settings in the object tool
object_paste_params p;
p.minScale = scale;
p.maxScale = scale;
global->get_view()->_world.get()->
addM2(filename,pos,scale,math::degrees::vec3(rotation), &p);
});
state->set_function("vec",[](float x, float y, float z){
return math::vector_3d(x,y,z);
});
state->set_function("add_wmo",[global](
std::string const& filename
, math::vector_3d const& pos
, math::vector_3d const& rotation)
{
global->get_view()->_world.get()->addWMO(
filename
, pos
, math::degrees::vec3(rotation));
});
state->set_function("get_map_id",[global]()
{
return global->get_view()->_world.get()->getMapID();
});
state->set_function("get_area_id",[global](
math::vector_3d const& pos)
{
return global->get_view()->_world.get()->getAreaID(pos);
});
state->set_function("cam_pitch",[global]()
{
return global->get_view()->_camera.pitch()._;
});
state->set_function("cam_yaw",[global]()
{
return global->get_view()->_camera.yaw()._;
});
state->set_function("holding_alt",[global]()
{
return global->get_view()->_mod_alt_down;
});
state->set_function("holding_shift",[global]()
{
return global->get_view()->_mod_shift_down;
});
state->set_function("holding_ctrl",[global]()
{
return global->get_view()->_mod_ctrl_down;
});
state->set_function("holding_space",[global]()
{
return global->get_view()->_mod_space_down;
});
state->set_function("holding_left_mouse",[global]()
{
return global->get_view()->leftMouse;
});
state->set_function("holding_right_mouse",[global]()
{
return global->get_view()->rightMouse;
});
state->set_function("print",[global](sol::variadic_args va)
{
std::string str = "";
for(auto v : va)
{
switch (v.get_type())
{
case sol::type::boolean:
str += std::to_string((bool)v);
break;
case sol::type::number:
str += std::to_string(v.get<float>());
break;
case sol::type::string:
str += v.get<std::string>();
break;
case sol::type::table:
// TODO: implement
str += "{table}";
break;
}
}
return global->addLog(str);
});
}
}
}

View File

@@ -0,0 +1,12 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#pragma once
#include <math/vector_3d.hpp>
namespace noggit {
namespace scripting {
class scripting_tool;
class script_context;
void register_global(script_context * state);
}
}

View File

@@ -0,0 +1,187 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#include <noggit/scripting/script_image.hpp>
#include <noggit/scripting/scripting_tool.hpp>
#include <noggit/scripting/script_exception.hpp>
#include <noggit/scripting/script_context.hpp>
#include <noggit/scripting/script_filesystem.hpp>
#include <sol/sol.hpp>
#include <lodepng.h>
namespace noggit
{
namespace scripting
{
void image::resize(int width, int height)
{
if(width<=0||height<=0)
{
throw script_exception(
"img_resize",
std::string("tried to resize to invalid image size: x=")
+ std::to_string(width)
+ std::string(" y=")
+ std::to_string(height)
);
}
_size = width*height*4;
_width = width;
_height = height;
_image.resize(_width * _height * 4);
}
image::image(script_context * ctx, std::string const& path)
: script_object(ctx)
{
unsigned error = lodepng::decode(_image, _width, _height, path);
if (error)
{
throw script_exception(
"img_load_png",
"failed to load png image with error code:"
+ std::to_string (error));
}
resize(_width, _height);
}
image::image(script_context * ctx, int width, int height)
: script_object(ctx)
{
resize(width,height);
}
int image::width() const
{
return _width;
}
int image::height() const
{
return _height;
}
int image::get_index(int x, int y) const
{
int index = ((x + y * _width) * 4);
if(index<0||index>=_size)
{
throw script_exception(
"img_get_index",
"image coordinates out of bounds: x="
+ std::to_string(x)
+ " y="
+ std::to_string(y)
+ " width="
+ std::to_string(_width)
+ " height="
+ std::to_string(_height));
}
return index;
}
unsigned image::get_pixel(int x, int y) const
{
unsigned index = get_index(x, y);
return get_image()[index] << 24
| get_image()[index + 1] << 16
| get_image()[index + 2] << 8
| get_image()[index + 3];
}
float image::get_alpha(int x, int y) const
{
return float(get_pixel(x,y) & 0xff)/255.0;
}
float image::get_blue(int x, int y) const
{
return float((get_pixel(x,y) >> 8) & 0xff)/255.0;
}
float image::get_green(int x, int y) const
{
return float((get_pixel(x,y) >> 16) & 0xff)/255.0;
}
float image::get_red(int x, int y) const
{
return float((get_pixel(x,y) >> 24) & 0xff)/255.0;
}
void image::set_pixel(int x, int y, unsigned value)
{
unsigned index = get_index(x, y);
get_image_w()[index] = (value << 24);
get_image_w()[index + 1] = (value << 16) & 0xff;
get_image_w()[index + 2] = (value << 8) & 0xff;
get_image_w()[index + 3] = (value) & 0xff;
}
void image::set_pixel_floats(int x, int y, float r, float g, float b, float a)
{
unsigned index = get_index(x, y);
get_image_w()[index] = std::max(std::min(int(r * 255),255),0);
get_image_w()[index + 1] = std::max(std::min(int(g * 255),255),0);
get_image_w()[index + 2] = std::max(std::min(int(b * 255),255),0);
get_image_w()[index + 3] = std::max(std::min(int(a * 255),255),0);
}
void image::save(std::string const& filename)
{
auto writable_path = get_writable_path("image::save", state(), filename);
mkdirs(writable_path.string());
unsigned error = lodepng::encode(writable_path.string(), get_image(), _width, _height);
if (error)
{
throw script_exception(
"img_save",
"failed to save image with error "
+ std::to_string (error));
}
}
float image::gradient_scale(float rel) const
{
if(rel<0||rel>=1)
{
throw script_exception(
"img_gradient_scale",
"relative image coordinate out of bounds: "
+ std::to_string(rel)
+ " (should be >= 0 and < 1)");
}
int x = std::floor(rel * float(_width));
// read red channel, but it shouldn't matter.
return float(get_image()[x * 4]) / 255.0;
}
void register_image(script_context * state)
{
state->new_usertype<image>("image"
, "get_index", &image::get_index
, "get_blue", &image::get_blue
, "get_red", &image::get_red
, "get_alpha", &image::get_alpha
, "get_green", &image::get_green
, "get_pixel", &image::get_pixel
, "gradient_scale", &image::gradient_scale
, "set_pixel", &image::set_pixel
, "set_pixel_floats", sol::overload(
&image::set_pixel_floats
, &image::set_pixel_floats_1
)
, "save", &image::save
, "width", &image::width
, "height", &image::height
);
state->set_function("create_image",[state](int width ,int height){
return std::make_shared<image>(state, width,height);
});
state->set_function("load_png", [state](std::string const& path) {
return std::make_shared<image>(state, path);
});
}
} // namespace scripting
} // namespace noggit

View File

@@ -0,0 +1,49 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#pragma once
#include <noggit/scripting/script_object.hpp>
#include <vector>
#include <string>
#include <memory>
namespace noggit
{
namespace scripting
{
class scripting_tool;
class script_context;
class image: public script_object
{
public:
image(script_context * ctx, std::string const& path);
image(script_context * ctx, int width, int height);
std::vector<unsigned char> _image;
int get_index(int x, int y) const;
unsigned get_pixel(int x, int y) const;
float gradient_scale(float rel) const;
void set_pixel(int x, int y, unsigned value);
void set_pixel_floats(int x, int y, float r, float g, float b, float a /*= 1.0*/);
void set_pixel_floats_1(int x, int y, float r, float g, float b)
{
set_pixel_floats(x,y,r,g,b,1.0);
}
void save(std::string const& filename);
int width() const;
int height() const;
float get_blue(int x, int y) const;
float get_green(int x, int y) const;
float get_red(int x, int y) const;
float get_alpha(int x, int y) const;
private:
void resize(int width, int height);
unsigned char const * get_image() const {return _image.data();}
unsigned char * get_image_w() {return _image.data();}
unsigned _width = 0;
unsigned _height = 0;
unsigned _size = 0;
};
void register_image(script_context * state);
} // namespace scripting
} // namespace noggit

View File

@@ -0,0 +1,98 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#include <noggit/scripting/script_math.hpp>
#include <noggit/scripting/script_context.hpp>
#include <noggit/scripting/scripting_tool.hpp>
#include <sol/sol.hpp>
#include <cmath>
namespace noggit
{
namespace scripting
{
int round(float a1) { return std::floor(a1); }
float pow(float a1, float a2) { return ::pow(a1, a2); }
float log10(float arg) { return ::log10(arg); }
float log(float arg) { return ::log(arg); }
int ceil(float arg) { return ::ceil(arg); }
int floor(float arg) { return std::floor(arg); }
float exp(float arg) { return ::exp(arg); }
float cbrt(float arg) { return ::cbrt(arg); }
float acosh(float arg) { return ::acosh(arg); }
float asinh(float arg) { return ::asinh(arg); }
float atanh(float arg) { return ::atanh(arg); }
float cosh(float arg) { return ::cosh(arg); }
float sinh(float arg) { return ::sinh(arg); }
float tanh(float arg) { return ::tanh(arg); }
float acos(float arg) { return ::acos(arg); }
float asin(float arg) { return ::asin(arg); }
float atan(float arg) { return ::atan(arg); }
float cos(float arg) { return ::cos(arg); }
float sin(float arg) { return ::sin(arg); }
float tan(float arg) { return ::tan(arg); }
float sqrt(float arg) { return ::sqrt(arg); }
float abs(float arg) { return ::abs(arg); }
float lerp(float from, float to, float ratio) { return from + ratio * (to - from); }
float dist_2d(math::vector_3d const& from, math::vector_3d const& to)
{
return std::sqrt(std::pow(from.x - to.x, 2) + std::pow(from.z - to.z, 2));
}
int dist_2d_compare(math::vector_3d const& from, math::vector_3d const& to, float compare)
{
float dist = std::pow(from.x - to.x, 2) + std::pow(from.z - to.z, 2);
compare = std::pow(compare, 2);
return dist > compare ? 1 : dist == compare ? 0 : -1;
}
math::vector_3d rotate_2d(math::vector_3d const& point, math::vector_3d const& origin, float angle)
{
float s = std::sin(angle * 0.0174532925);
float c = std::cos(angle * 0.0174532925);
float lx = point.x - origin.x;
float lz = point.z - origin.z;
float nx = lx * c - lz * s + origin.x;
float nz = lx * s + lz * c + origin.z;
return math::vector_3d(nx, point.y, nz);
}
void register_math(script_context * state)
{
state->set_function("round",round);
state->set_function("pow",pow);
state->set_function("log10",log10);
state->set_function("log",log);
state->set_function("ceil",ceil);
state->set_function("floor",floor);
state->set_function("exp",exp);
state->set_function("cbrt",cbrt);
state->set_function("acosh",acosh);
state->set_function("asinh",asinh);
state->set_function("atanh",atanh);
state->set_function("cosh",cosh);
state->set_function("sinh",sinh);
state->set_function("tanh",tanh);
state->set_function("acos",acos);
state->set_function("asin",asin);
state->set_function("atan",atan);
state->set_function("cos",cos);
state->set_function("sin",sin);
state->set_function("tan",tan);
state->set_function("sqrt",sqrt);
state->set_function("abs",abs);
state->set_function("lerp",lerp);
state->set_function("dist_2d",dist_2d);
state->set_function("dist_2d_compare",dist_2d_compare);
state->set_function("rotate_2d",rotate_2d);
state->new_usertype<math::vector_3d>("vector_3d"
, "x", &math::vector_3d::x
, "y", &math::vector_3d::y
, "z", &math::vector_3d::z
);
}
} // namespace scripting
} // namespace noggit

View File

@@ -0,0 +1,44 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#pragma once
#include <math/vector_3d.hpp>
#include <memory>
#include <string>
namespace noggit
{
namespace scripting
{
class scripting_tool;
class script_context;
int round(float a1);
float pow(float a1, float a2);
float log10(float arg);
float log(float arg);
int ceil(float arg);
int floor(float arg);
float exp(float arg);
float cbrt(float arg);
float acosh(float arg);
float asinh(float arg);
float atanh(float arg);
float cosh(float arg);
float sinh(float arg);
float tanh(float arg);
float acos(float arg);
float asin(float arg);
float atan(float arg);
float cos(float arg);
float sin(float arg);
float tan(float arg);
float sqrt(float arg);
float abs(float arg);
float lerp(float from, float to, float amount);
float dist_2d(math::vector_3d const& from, math::vector_3d const& to);
int dist_2d_compare(math::vector_3d const& from, math::vector_3d const& to, float dist);
math::vector_3d rotate_2d(math::vector_3d const& point, math::vector_3d const& origin, float angleDeg);
void register_math(script_context * state);
} // namespace scripting
} // namespace noggit

View File

@@ -0,0 +1,160 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#include <noggit/scripting/script_model.hpp>
#include <noggit/scripting/scripting_tool.hpp>
#include <noggit/scripting/script_context.hpp>
#include <noggit/scripting/script_exception.hpp>
#include <noggit/World.h>
#include <noggit/ModelInstance.h>
#include <noggit/WMOInstance.h>
#include <noggit/ui/ObjectEditor.h>
#include <util/visit.hpp>
#include <sol/sol.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/case_conv.hpp>
namespace noggit
{
namespace scripting
{
model::model (script_context * ctx, SceneObject* object)
: script_object(ctx)
, _object (object)
{}
math::vector_3d model::get_pos()
{
return _object->pos;;
}
void model::set_pos(math::vector_3d& pos)
{
world()->updateTilesEntry(_object, model_update::remove);
_object->pos = pos;
_object->recalcExtents();
world()->updateTilesEntry(_object, model_update::add);
}
math::vector_3d model::get_rot()
{
return {_object->dir.x._, _object->dir.y._, _object->dir.z._};
}
void model::set_rot(math::vector_3d& rot)
{
math::degrees::vec3 dir = math::degrees::vec3{ rot };
world()->updateTilesEntry(_object, model_update::remove);
_object->dir = dir;
_object->recalcExtents();
world()->updateTilesEntry(_object, model_update::add);
}
float model::get_scale()
{
return _object->scale;
}
void model::set_scale(float scale)
{
if (_object->which() != eWMO)
{
world()->updateTilesEntry(_object, model_update::remove);
_object->scale = scale;
_object->recalcExtents();
world()->updateTilesEntry(_object, model_update::add);
}
}
unsigned model::get_uid()
{
return _object->uid;
}
std::string model::get_filename()
{
return _object->getFilename();
}
bool model::has_filename(std::string const& name)
{
std::string copy = std::string(name);
boost::to_lower(copy);
std::replace(copy.begin(),copy.end(),'\\','/');
return copy == get_filename();
}
void model::remove()
{
std::vector<selection_type> type{_object};
world()->deleteObjects(type);
}
void model::replace(std::string const& filename)
{
if (get_filename() == filename)
{
return;
}
remove();
if (boost::ends_with(filename, ".wmo"))
{
_object =
world()->addWMOAndGetInstance(filename, get_pos(), math::degrees::vec3 {get_rot()});
}
else
{
auto params = object_paste_params();
_object =
world()->addM2AndGetInstance(filename, get_pos(), get_scale(), math::degrees::vec3 {get_rot()}, &params);
}
}
void collect_models(
script_context * ctx
, World * world
, math::vector_3d const& min
, math::vector_3d const& max
, std::vector<model> & vec
)
{
world->getModelInstanceStorage().for_each_m2_instance([&](ModelInstance& mod)
{
if (mod.pos.x >= min.x && mod.pos.x <= max.x
&& mod.pos.z >= min.z && mod.pos.z <= max.z)
{
vec.push_back(model(ctx, &mod));
}
});
world->getModelInstanceStorage().for_each_wmo_instance([&](WMOInstance& mod)
{
if (mod.pos.x >= min.x && mod.pos.x <= max.x
&& mod.pos.z >= min.z && mod.pos.z <= max.z)
{
vec.push_back(model(ctx, &mod));
}
});
}
void register_model(script_context * state)
{
state->new_usertype<model>("model"
, "get_pos", &model::get_pos
, "set_pos", &model::set_pos
, "get_rot", &model::get_rot
, "set_rot", &model::set_rot
, "get_scale", &model::get_scale
, "set_scale", &model::set_scale
, "get_uid", &model::get_uid
, "remove", &model::remove
, "get_filename", &model::get_filename
, "has_filename", &model::has_filename
, "replace", &model::replace
);
}
} // namespace scripting
} // namespace noggit

View File

@@ -0,0 +1,57 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#pragma once
#include <noggit/scripting/script_object.hpp>
#include <math/vector_3d.hpp>
#include <boost/variant.hpp>
class World;
class SceneObject;
namespace noggit
{
namespace scripting
{
class scripting_tool;
class script_context;
class model : public script_object
{
public:
model(script_context * ctx, SceneObject* object);
math::vector_3d get_pos();
void set_pos(math::vector_3d& pos);
math::vector_3d get_rot();
void set_rot(math::vector_3d& rot);
float get_scale();
void set_scale(float scale);
bool has_filename(std::string const& name);
unsigned get_uid();
void remove();
std::string get_filename();
void replace(std::string const& filename);
private:
SceneObject* _object;
};
void collect_models(
script_context * ctx
, World * world
, math::vector_3d const& min
, math::vector_3d const& max
, std::vector<model>& vec
);
void register_model(script_context * state);
} // namespace scripting
} // namespace noggit

View File

@@ -0,0 +1,217 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#include <noggit/scripting/script_noise.hpp>
#include <noggit/scripting/scripting_tool.hpp>
#include <noggit/scripting/script_exception.hpp>
#include <noggit/scripting/script_context.hpp>
#include <boost/algorithm/string.hpp>
namespace noggit
{
namespace scripting
{
float noisemap::get_index(std::string const& caller, int x, int y)
{
unsigned index = x + y * _width;
if(index<0||index>=_size)
{
throw script_exception(
caller,
std::string("noise coordinates out of bounds: x=")
+ std::to_string(x)
+ std::string(" y=")
+ std::to_string(y)
+ std::string(" width=")
+ std::to_string(_width)
+ std::string(" height=")
+ std::to_string(_height));
}
return get_map()[index];
}
float noisemap::get(math::vector_3d& pos)
{
return get_index("noise_get",std::round(pos.x) - _start_x, std::round(pos.z) - _start_y);
}
bool noisemap::is_highest(math::vector_3d& pos, int check_radius)
{
int x = std::round(pos.x) - _start_x;
int z = std::round(pos.z) - _start_y;
float own = get_index("noise_is_highest", x, z);
for (int xc = x - check_radius; xc < x + check_radius; ++xc)
{
for (int zc = z - check_radius; zc < z + check_radius; ++zc)
{
if (xc == x && zc == z)
{
continue;
}
if (get_index("noise_is_highest",xc, zc) > own)
{
return false;
}
}
}
return true;
}
void noisemap::set(int x, int y, float value)
{
unsigned index = x + y * _width;
if(index<0||index>=_size)
{
throw script_exception(
"noisemap::set",
std::string("noisemap coordinates out of bounds: x=")
+ std::to_string(x)
+ std::string(" y=")
+ std::to_string(y)
+ std::string(" width=")
+ std::to_string(_width)
+ std::string(" height=")
+ std::to_string(_height));
}
get_map()[index] = value;
}
noisemap::noisemap(
script_context * ctx
, unsigned start_x
, unsigned start_y
, unsigned width
, unsigned height
, float frequency
, std::string const& algorithm
, std::string const& seed)
: script_object(ctx)
{
if(width<=0||height<=0)
{
throw script_exception(
"make_script_noise",
std::string("invalid noise map size:")
+ " width="
+ std::to_string(width)
+ " height="
+ std::to_string(height)
);
}
_width = width;
_height = height;
_start_x = start_x;
_start_y = start_y;
_size = width*height;
_noise.resize(_size);
auto upper = boost::algorithm::to_upper_copy<std::string>(algorithm);
FastNoise::SmartNode<> generator = nullptr;
if(upper=="SIMPLEX")
{
generator = FastNoise::New<FastNoise::Simplex>();
}
else if(upper=="PERLIN")
{
generator = FastNoise::New<FastNoise::Perlin>();
}
else if(upper=="VALUE")
{
generator = FastNoise::New<FastNoise::Value>();
}
else if(upper=="FRACTAL")
{
generator = FastNoise::New<FastNoise::FractalFBm>();
}
else if(upper=="CELLULAR")
{
generator = FastNoise::New<FastNoise::CellularValue>();
}
else if(upper=="WHITE")
{
generator = FastNoise::New<FastNoise::White>();
}
else
{
generator = FastNoise::NewFromEncodedNodeTree(algorithm.c_str());
}
generator->GenUniformGrid2D(
get_map()
, start_x
, start_y
, width
, height
, frequency
, std::hash<std::string>()(std::string(seed))
);
}
math::vector_3d noisemap::start()
{
return math::vector_3d(_start_x,0,_start_y);
}
unsigned noisemap::width()
{
return _width;
}
unsigned noisemap::height()
{
return _height;
}
std::shared_ptr<noisemap> make_noise(
script_context * ctx
, int x_start
, int y_start
, int x_size
, int y_size
, float frequency
, std::string const& algorithm
, std::string const& seed)
{
return std::make_shared<noisemap>( ctx
, x_start
, y_start
, x_size
, y_size
, frequency
, algorithm
, seed);
}
void register_noise(script_context * state)
{
state->new_usertype<noisemap>("noisemap"
, "get", &noisemap::get
, "is_highest", &noisemap::is_highest
, "set", &noisemap::set
, "start", &noisemap::start
, "width", &noisemap::width
, "height", &noisemap::height
);
state->set_function("make_noise",[state](
int sx
, int sy
, int width
, int height
, float frequency
, std::string const& algorithm
, std::string const& seed)
{
return make_noise( state
, sx
, sy
, width
, height
, frequency
, algorithm
, seed
);
});
}
} // namespace scripting
} // namespace noggit

View File

@@ -0,0 +1,61 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#pragma once
#include <noggit/scripting/script_selection.hpp>
#include <noggit/scripting/script_object.hpp>
#include <math/vector_3d.hpp>
#include <FastNoise/FastNoise.h>
#include <vector>
#include <string>
#include <memory>
namespace noggit
{
namespace scripting
{
class script_context;
class noisemap: public script_object
{
public:
noisemap(script_context * ctx
, unsigned start_x
, unsigned start_y
, unsigned width
, unsigned height
, float frequency
, std::string const& algorithm
, std::string const& seed);
float get(math::vector_3d &pos);
bool is_highest(math::vector_3d &pos, int check_radius);
void set(int x, int y, float value);
math::vector_3d start();
unsigned width();
unsigned height();
private:
std::vector<float> _noise;
float get_index(std::string const& caller, int x, int y);
float *get_map() { return _noise.data(); };
unsigned _width;
unsigned _height;
unsigned _start_x;
unsigned _start_y;
unsigned _size;
};
std::shared_ptr<noisemap> make_noise(
script_context * ctx
, int start_x
, int start_y
, int width
, int height
, float frequency
, std::string const& algorithm
, std::string const& seed);
void register_noise(script_context * state);
} // namespace scripting
} // namespace noggit

View File

@@ -0,0 +1,62 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#include <noggit/scripting/script_object.hpp>
#include <noggit/scripting/script_context.hpp>
#include <noggit/scripting/scripting_tool.hpp>
#include <noggit/World.h>
namespace noggit {
namespace scripting {
script_object::script_object(script_context * state)
: _state(state)
{}
sol::object script_object::set(const std::string& key, sol::stack_object obj)
{
initialize_table();
_table[key] = obj;
return obj;
}
bool script_object::has_table()
{
return _initialized;
}
World * script_object::world()
{
return _state->world();
}
void script_object::initialize_table()
{
if(!_initialized)
{
_table = _state->create_table();
_initialized = true;
}
}
sol::object script_object::get(const std::string& key)
{
initialize_table();
return _table[key];
}
sol::table script_object::table()
{
initialize_table();
return _table;
}
script_context * script_object::state()
{
return _state;
}
scripting_tool * script_object::tool()
{
return _state->tool();
}
}
}

View File

@@ -0,0 +1,89 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#pragma once
#include <noggit/scripting/script_exception.hpp>
#include <sol/sol.hpp>
class World;
namespace noggit {
namespace scripting {
class script_context;
class scripting_tool;
class script_object {
public:
// TODO: We can probably get this in a more intelligent way
script_object(script_context * state);
virtual sol::object set(const std::string& key, sol::stack_object obj);
virtual sol::object get(const std::string& key);
script_context * state();
scripting_tool * tool();
World * world();
sol::table table();
bool has_table();
protected:
sol::table _table;
void initialize_table();
private:
bool _initialized = false;
script_context * _state;
};
template <typename O, typename ...Ts>
class lua_function {
public:
lua_function(O * obj, std::string const& func)
: _obj(obj)
, _func(func)
{}
bool exists()
{
if (!_obj->has_table())
{
return false;
}
auto fn = _obj->table()[_func];
if (!fn.valid())
{
return false;
}
if (fn.get_type() == sol::type::function)
{
return true;
}
return false;
}
void call_if_exists(std::string caller, Ts...args)
{
if (exists()) call(caller, args...);
}
void call(std::string caller, Ts...args)
{
if(!exists())
{
throw script_exception(caller,"calling null function");
}
sol::protected_function fn = _obj->table()[_func];
auto ret = fn(_obj, args...);
if (!ret.valid())
{
sol::error err = ret;
throw script_exception(caller, err.what());
}
}
private:
O * _obj;
std::string _func;
};
#define LUA_MEMBER_FUNC(selftype, type,name) lua_function<selftype, type> name = lua_function<selftype, type>(this,#name);
}
}

View File

@@ -0,0 +1,55 @@
#include <noggit/scripting/script_procedures.hpp>
#include <noggit/scripting/script_image.hpp>
#include <noggit/scripting/script_tex.hpp>
#include <noggit/scripting/script_math.hpp>
#include <noggit/scripting/script_context.hpp>
#include <noggit/scripting/script_selection.hpp>
#include <math/vector_3d.hpp>
namespace noggit {
namespace scripting {
void procedures::paint_texture(
selection & sel
, image const& img
, int layer
, float pressure
, float angle
)
{
auto center = math::vector_3d(sel.min().x + (sel.max().x - sel.min().x) / 2, 0, sel.min().z + (sel.max().z - sel.min().z) / 2);
auto outer_radius = (sel.max().x - sel.min().x) / 2;
int width = img.width();
int height = img.height();
float half_width = float(width) / 2;
float half_height = float(height) / 2;
for (auto & tex : sel.textures_raw())
{
auto global_pos = tex.get_pos_2d();
auto dist = dist_2d(global_pos, center) / outer_radius;
global_pos = rotate_2d(global_pos, center, angle);
auto rel_x = (global_pos.x - center.x) / outer_radius;
auto rel_z = (global_pos.z - center.z) / outer_radius;
if (!(rel_x < -1 || rel_x > 1 || rel_z < -1 || rel_z > 1))
{
auto img_x = round(half_width + half_width * rel_x);
auto img_z = round(half_height + half_height * rel_z);
if (img_x >= 0 && img_x < width && img_z >= 0 && img_z < height) {
auto old = tex.get_alpha(layer);
tex.set_alpha(layer, old + (img.get_red(img_x, img_z) * pressure * (1 - dist)));
}
}
}
}
void register_procedures(script_context* state)
{
state->new_usertype<procedures>("procedures_class"
, "paint_texture", &procedures::paint_texture
);
state->set("procedures", procedures());
}
}
}

View File

@@ -0,0 +1,24 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#pragma once
#include <vector>
namespace noggit {
namespace scripting {
class selection;
class image;
class script_context;
class procedures {
public:
void paint_texture(
selection & sel
, image const& image
, int layer
, float pressure
, float angle
);
};
void register_procedures(script_context * state);
}
}

View File

@@ -0,0 +1,153 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#include <noggit/scripting/script_profiles.hpp>
#include <noggit/scripting/scripting_tool.hpp>
#include <noggit/scripting/script_settings.hpp>
#include <noggit/scripting/script_context.hpp>
// TODO: duplicate
#define CUR_PROFILE_PATH "__cur_profile"
namespace noggit
{
namespace scripting
{
script_profiles::script_profiles(noggit::scripting::scripting_tool * tool)
: QGroupBox("Script Profiles"), _tool(tool)
{
_select_column = new QGridLayout(this);
_select_column->setContentsMargins(1, 1, 1, 1);
_selection = new QComboBox(this);
_selection->addItem("Default");
_remove_button = new QPushButton("X", this);
_name_entry = new QLineEdit(this);
_create_button = new QPushButton("Add", this);
_select_column->addWidget(_selection, 0, 0);
_select_column->addWidget(_remove_button, 0, 1);
_select_column->addWidget(_name_entry, 1, 0);
_select_column->addWidget(_create_button, 1, 1);
connect(_selection, QOverload<int>::of(&QComboBox::activated), this, [this](auto index) {
select_profile_gui(index);
});
connect(_remove_button, &QPushButton::released, this, [this]() {
auto script_name = _tool->get_context()->get_selected_name();
if (script_name.size() == 0)
{
// TODO: error?
return;
}
auto index = _selection->currentIndex();
// do not allow deleting default settings
if (index == 0)
{
return;
}
auto text = _selection->itemText(index).toStdString();
_selection->removeItem(index);
auto json = _tool->get_settings()->get_raw_json();
if (json->contains(script_name))
{
if ((*json)[script_name].contains(text))
{
(*json)[script_name].erase(text);
}
}
select_profile_gui(0);
});
connect(_create_button, &QPushButton::released, this, [this]() {
auto script_name = _tool->get_context()->get_selected_name();
// do not allow invalid script
if (script_name.size() == 0)
return;
auto newText = _name_entry->text();
// do not allow empty profiles
if (newText.isEmpty())
return;
auto count = _selection->count();
for (int i = 0; i < count; ++i)
{
// do not allow duplicate profiles
if (_selection->itemText(i) == newText)
{
return;
}
}
_name_entry->clear();
_selection->addItem(newText);
auto json = _tool->get_settings()->get_raw_json();
if (!(*json)[script_name].contains(newText.toStdString()))
{
if ((*json)[script_name].contains(_cur_profile))
{
(*json)[script_name][newText.toStdString()] = (*json)[script_name][_cur_profile];
}
}
_selection->setCurrentIndex(count);
select_profile_gui(count);
});
}
void script_profiles::select_profile_gui(int profile)
{
select_profile(profile);
_tool->clearDescription();
_tool->get_context()->select_script(_tool->get_context()->get_selection());
// string array / brush settings have changed
_tool->get_settings()->initialize();
}
void script_profiles::select_profile(int profile)
{
_tool->get_settings()->clear();
_cur_profile = _selection->itemText(profile).toStdString();
auto n = _tool->get_context()->get_selected_name();
_selection->setCurrentIndex(profile);
(*_tool->get_settings()->get_raw_json())[n][CUR_PROFILE_PATH] = _cur_profile;
}
std::string script_profiles::get_cur_profile()
{
return _cur_profile;
}
void script_profiles::clear()
{
_selection->clear();
}
void script_profiles::add_profile(std::string const& profile)
{
_selection->addItem(QString::fromStdString (profile));
}
int script_profiles::profile_count()
{
return _selection->count();
}
std::string script_profiles::get_profile(int index)
{
return _selection->itemText(index).toStdString();
}
} // namespace scripting
} // namespace noggit

View File

@@ -0,0 +1,37 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#pragma once
#include <QtWidgets/QGroupBox>
#include <QtWidgets/QGridLayout>
#include <QtWidgets/QComboBox>
#include <QtWidgets/QLineEdit>
#include <QtWidgets/QPushButton>
namespace noggit {
namespace scripting {
class scripting_tool;
class script_settings;
class script_profiles : public QGroupBox {
public:
script_profiles(noggit::scripting::scripting_tool * tool);
void select_profile(int profile);
std::string get_cur_profile();
void clear();
void add_profile(std::string const& profile);
int profile_count();
std::string get_profile(int index);
private:
noggit::scripting::scripting_tool* _tool;
QGridLayout* _select_column;
QComboBox* _selection;
QLineEdit* _name_entry;
QPushButton* _remove_button;
QPushButton* _create_button;
std::string _cur_profile;
void on_change_script(int selection);
void select_profile_gui(int profile);
};
}
}

View File

@@ -0,0 +1,94 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#include <noggit/scripting/script_random.hpp>
#include <noggit/scripting/script_exception.hpp>
#include <noggit/scripting/scripting_tool.hpp>
#include <noggit/scripting/script_context.hpp>
#include <sol/sol.hpp>
namespace noggit
{
namespace scripting
{
random::random(script_context * ctx, unsigned seed)
: script_object(ctx)
, _state(seed)
{
}
random::random(script_context * ctx, std::string const& seed)
: script_object(ctx)
, _state(std::hash<std::string>()(seed))
{
}
random::random(script_context * ctx)
: script_object(ctx)
, _state(std::chrono::high_resolution_clock::now().time_since_epoch().count())
{
}
long random::integer(long low, long high)
{
if (low == high)
{
return low;
}
if(low>=high)
{
throw script_exception(
"rand_int64",
"random lower bound "+ std::to_string(low) + " >= higher bound " + std::to_string(high));
}
return std::uniform_int_distribution<long>(low,high-1)(_state);
}
double random::real(double low, double high)
{
if (low == high)
{
return low;
}
if(low>=high)
{
throw script_exception(
"rand_double",
"random lower bound "+ std::to_string(low) + " >= higher bound " + std::to_string(high));
}
double val;
do {
val = std::uniform_real_distribution<double>(low,high)(_state);
} while(val == high);
return val;
}
std::shared_ptr<random> random_from_seed(script_context * ctx, std::string const& seed)
{
return std::make_shared<random>(ctx, std::string(seed));
}
std::shared_ptr<random> random_from_time(script_context * ctx)
{
return std::make_shared<random>(ctx);
}
void register_random(script_context * state)
{
state->new_usertype<random>("random"
, "integer", &random::integer
, "real", &random::real
);
state->set_function("random_from_seed",[state](std::string const& seed)
{
return random_from_seed(state, seed);
});
state->set_function("random_from_time",[state]()
{
return random_from_time(state);
});
}
} // namespace scripting
} // namespace noggit

View File

@@ -0,0 +1,32 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#pragma once
#include <noggit/scripting/script_object.hpp>
#include <random>
#include <chrono>
#include <memory>
namespace noggit
{
namespace scripting
{
class scripting_tool;
class script_context;
class random: public script_object
{
public:
random(script_context * state, unsigned seed);
random(script_context * state, std::string const& seed);
random(script_context * state);
long integer(long low, long high);
double real(double low, double high);
private:
std::minstd_rand _state;
};
std::shared_ptr<random> random_from_seed(script_context * state, std::string const& seed);
std::shared_ptr<random> random_from_time(script_context * state);
void register_random(script_context * state);
} // namespace scripting
} // namespace noggit

View File

@@ -0,0 +1,47 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#pragma once
#include <noggit/scripting/scripting_tool.hpp>
#include <noggit/scripting/script_brush.hpp>
#include <noggit/scripting/script_global.hpp>
#include <noggit/scripting/script_tex.hpp>
#include <noggit/scripting/script_vert.hpp>
#include <noggit/scripting/script_chunk.hpp>
#include <noggit/scripting/script_selection.hpp>
#include <noggit/scripting/script_random.hpp>
#include <noggit/scripting/script_noise.hpp>
#include <noggit/scripting/script_model.hpp>
#include <noggit/scripting/script_math.hpp>
#include <noggit/scripting/script_image.hpp>
#include <noggit/scripting/script_filesystem.hpp>
#include <noggit/scripting/script_standard_brush.hpp>
#include <noggit/scripting/script_settings.hpp>
#include <noggit/scripting/script_procedures.hpp>
#include <sol/sol.hpp>
namespace noggit {
namespace scripting {
namespace {
void register_functions(script_context * lua)
{
// Register your functions / add registry functions here!
register_script_brush(lua);
register_model(lua);
register_global(lua);
register_vert(lua);
register_tex(lua);
register_chunk(lua);
register_selection(lua);
register_random(lua);
register_noise(lua);
register_math(lua);
register_image(lua);
register_filesystem(lua);
register_standard_brush(lua);
register_procedures(lua);
register_settings(lua);
}
}
}
}

View File

@@ -0,0 +1,183 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#include <noggit/scripting/script_selection.hpp>
#include <noggit/scripting/script_context.hpp>
#include <noggit/scripting/script_exception.hpp>
#include <noggit/scripting/script_noise.hpp>
#include <noggit/scripting/scripting_tool.hpp>
#include <noggit/MapView.h>
#include <noggit/World.h>
#include <math/vector_3d.hpp>
namespace noggit
{
namespace scripting
{
selection::selection(script_context * ctx, std::string const&,math::vector_3d const& point1, math::vector_3d const& point2)
: script_object(ctx)
, _world(ctx->world())
{
_min = math::vector_3d(
std::min(point1.x, point2.x),
std::min(point1.y, point2.y),
std::min(point1.z, point2.z));
_max = math::vector_3d(
std::max(point1.x, point2.x),
std::max(point1.y, point2.y),
std::max(point1.z, point2.z));
_size = _max - _min;
_center = _min + (_size / 2);
}
math::vector_3d selection::center()
{
return _center;
}
math::vector_3d selection::min()
{
return _min;
}
math::vector_3d selection::max()
{
return _max;
}
math::vector_3d selection::size()
{
return _size;
}
std::shared_ptr<noisemap> selection::make_noise(
float frequency
, std::string const& algorithm
, std::string const& seed)
{
return noggit::scripting::make_noise(
state()
// padding to ensure we get no rounding errors (should be smaller?)
, std::floor(_min.x)-2
, std::floor(_min.z)-2
, std::ceil(_size.x)+4
, std::ceil(_size.z)+4
, frequency
, algorithm
, seed
);
}
std::vector<chunk> selection::chunks_raw()
{
std::vector<MapChunk*> mapChunks;
//_world->select_all_chunks_between(_min, _max, mapChunks); // todo
std::vector<chunk> chunks;
chunks.reserve(mapChunks.size());
for (auto& chnk : mapChunks) chunks.emplace_back(state(), chnk);
return chunks;
}
std::vector<vert> selection::verts_raw()
{
std::vector<vert> verts;
for (auto chunk : chunks_raw())
{
for (int i = 0; i < mapbufsize; ++i)
{
auto& v = chunk._chunk->mVertices[i];
if (v.x >= _min.x && v.x <= _max.x &&
v.z >= _min.z && v.z <= _max.z)
{
verts.emplace_back(state(),chunk._chunk,i);
}
}
}
return verts;
}
std::vector<tex> selection::textures_raw()
{
std::vector<tex> texvec;
for (auto chnk : chunks_raw())
{
collect_textures(state(), chnk._chunk, texvec, _min, _max);
}
return texvec;
}
std::vector<model> selection::models_raw()
{
std::vector<model> models;
collect_models(state(), world(), _min, _max, models);
return models;
}
sol::as_table_t<std::vector<chunk>> selection::chunks()
{
return sol::as_table(chunks_raw());
}
sol::as_table_t<std::vector<vert>> selection::verts()
{
return sol::as_table(verts_raw());
}
sol::as_table_t<std::vector<tex>> selection::textures()
{
return sol::as_table(textures_raw());
}
sol::as_table_t<std::vector<model>> selection::models()
{
return sol::as_table(models_raw());
}
void selection::apply()
{
for (auto& chnk : chunks_raw())
{
chnk.apply_all();
}
}
void register_selection(script_context* state)
{
state->new_usertype<selection>("selection"
, "center", &selection::center
, "min", &selection::min
, "max", &selection::max
, "size", &selection::size
, "apply", &selection::apply
, "verts", &selection::verts
, "tex", &selection::textures
, "models", &selection::models
, "chunks", &selection::chunks
, "make_noise", &selection::make_noise
);
state->set_function("select_origin", [state](
math::vector_3d const& origin
, float xRadius
, float zRadius = -1
)
{
if(zRadius <= 0)
{
zRadius = xRadius;
}
return std::make_shared<selection>(state, "select_origin",
math::vector_3d(origin.x - xRadius, 0, origin.z - zRadius),
math::vector_3d(origin.x + xRadius, 0, origin.z + zRadius));
});
state->set_function("select_between", [state](
math::vector_3d const& point1
, math::vector_3d const& point2
)
{
return std::make_shared<selection>(state, "select_between",
point1,point2);
});
}
} // namespace scripting
} // namespace noggit

View File

@@ -0,0 +1,69 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#pragma once
#include <noggit/scripting/script_object.hpp>
#include <noggit/scripting/script_model.hpp>
#include <noggit/scripting/script_chunk.hpp>
#include <math/vector_3d.hpp>
#include <vector>
#include <string>
#include <memory>
class MapChunk;
class World;
namespace noggit
{
namespace scripting
{
class script_context;
class model_iterator;
class vert_iterator;
class tex_iterator;
class noisemap;
class selection: public script_object
{
public:
selection( script_context * ctx
, std::string const& caller
, math::vector_3d const& point1
, math::vector_3d const& point2
);
std::shared_ptr<noisemap> make_noise(
float frequency
, std::string const& algorithm
, std::string const& seed
);
math::vector_3d center();
math::vector_3d min();
math::vector_3d max();
math::vector_3d size();
std::vector<chunk> chunks_raw();
std::vector<vert> verts_raw();
std::vector<tex> textures_raw();
std::vector<model> models_raw();
sol::as_table_t<std::vector<chunk>> chunks();
sol::as_table_t<std::vector<vert>> verts();
sol::as_table_t<std::vector<tex>> textures();
sol::as_table_t<std::vector<model>> models();
void apply();
private:
World* _world;
math::vector_3d _center;
math::vector_3d _min;
math::vector_3d _max;
math::vector_3d _size;
};
void register_selection(script_context * state);
} // namespace scripting
} // namespace noggit

View File

@@ -0,0 +1,522 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#include <noggit/scripting/script_settings.hpp>
#include <noggit/scripting/script_profiles.hpp>
#include <noggit/scripting/scripting_tool.hpp>
#include <noggit/scripting/script_context.hpp>
#include <sol/sol.hpp>
#include <boost/filesystem.hpp>
#include <nlohmann/json.hpp>
#include <iomanip>
#define INNER_RADIUS_PATH "__inner_radius"
#define OUTER_RADIUS_PATH "__outer_radius"
#define SCRIPT_FILE "script_settings.json"
namespace noggit
{
namespace scripting
{
script_settings::script_settings(scripting_tool *tool)
: QGroupBox("Script Settings"), _tool(tool)
{
_layout = new QVBoxLayout(this);
_layout->setContentsMargins(0, 1, 0, 1);
_radius_spin = new QDoubleSpinBox(this);
_radius_spin->setRange(0.0f, 1000.0f);
_radius_spin->setDecimals(2);
_radius_spin->setValue(_radius);
_radius_slider = new QSlider(Qt::Orientation::Horizontal, this);
_radius_slider->setRange(0, 1000);
_radius_slider->setSliderPosition((int)std::round(_radius));
_inner_radius_spin = new QDoubleSpinBox(this);
_inner_radius_spin->setRange(0.0f, 1.0f);
_inner_radius_spin->setDecimals(2);
_inner_radius_spin->setValue(_inner_radius);
_inner_radius_spin->setSingleStep(0.05f);
_inner_radius_slider = new QSlider(Qt::Orientation::Horizontal, this);
_inner_radius_slider->setRange(0, 100);
_inner_radius_slider->setSliderPosition((int)std::round(_inner_radius * 100));
_radius_group = new QGroupBox("Radius");
_radius_layout = new QFormLayout(_radius_group);
_radius_layout->addRow("Outer:", _radius_spin);
_radius_layout->addRow(_radius_slider);
_radius_layout->addRow("Inner:", _inner_radius_spin);
_radius_layout->addRow(_inner_radius_slider);
_custom_group = new QFrame();
_custom_layout = new QFormLayout(_custom_group);
_custom_group->setContentsMargins(0, 1, 0, 1);
_layout->addWidget(_radius_group);
_layout->addWidget(_custom_group);
connect(_radius_spin, qOverload<double>(&QDoubleSpinBox::valueChanged), [&](double v) {
_radius = v;
QSignalBlocker const blocker(_radius_slider);
_radius_slider->setSliderPosition((int)std::round(v));
set_json (OUTER_RADIUS_PATH, v);
});
connect(_radius_slider, &QSlider::valueChanged, [&](int v) {
_radius = v;
QSignalBlocker const blocker(_radius_spin);
_radius_spin->setValue(v);
set_json (OUTER_RADIUS_PATH, v);
});
connect(_inner_radius_spin, qOverload<double>(&QDoubleSpinBox::valueChanged), [&](double v) {
_inner_radius = v;
QSignalBlocker const blocker(_inner_radius_slider);
_inner_radius_slider->setSliderPosition((int)std::round(v * 100));
set_json (INNER_RADIUS_PATH, v);
});
connect(_inner_radius_slider, &QSlider::valueChanged, [&](int v) {
_inner_radius = v / 100.0f;
QSignalBlocker const blocker(_inner_radius_spin);
_inner_radius_spin->setValue(_inner_radius);
set_json (INNER_RADIUS_PATH, _inner_radius);
});
}
template <typename T>
T script_settings::get_json_safe(std::string const& key, T def, std::function<bool(nlohmann::basic_json<>)> check)
{
// TODO: this is terrible but accessing by reference didn't seem to work.
auto ssn = _tool->get_context()->get_selected_name();
auto prof = _tool->get_profiles()->get_cur_profile();
if(!_json[ssn][prof].contains(key))
{
_json[ssn][prof][key] = def;
return def;
}
auto v = _json[ssn][prof][key];
if (!check(v))
{
_json[ssn][prof][key] = def;
}
return _json[ssn][prof][key];
}
template <typename T>
T script_settings::get_json_unsafe(std::string const& key)
{
auto ssn = _tool->get_context()->get_selected_name();
auto prof = _tool->get_profiles()->get_cur_profile();
return (_json)[ssn][prof][key].get<T>();
}
template <typename T>
void script_settings::set_json(std::string const& key, T def)
{
auto ssn = _tool->get_context()->get_selected_name();
auto prof = _tool->get_profiles()->get_cur_profile();
_json[ssn][prof][key] = def;
}
// i don't remember why this was a macro
#define ADD_SLIDER(path, T, min, max, def, decimals, has_slider) \
double dp1 = decimals > 0 ? decimals + 5 : decimals + 1; \
auto spinner = new QDoubleSpinBox(this); \
spinner->setRange(min, max); \
spinner->setDecimals(decimals); \
spinner->setValue(def); \
auto slider = new QSlider(Qt::Orientation::Horizontal, this); \
slider->setRange(min *dp1, max *dp1); \
slider->setSliderPosition((int)std::round(def *dp1)); \
auto label = new QLabel(this); \
label->setText(name.c_str()); \
connect(spinner, qOverload<double>(&QDoubleSpinBox::valueChanged), [=](double v) { \
set_json<T>(path, (T)v); \
QSignalBlocker const blocker(slider); \
slider->setSliderPosition((int)std::round(v *dp1)); \
}); \
connect(slider, &QSlider::valueChanged, [=](int v) { \
double t = double(v) / dp1; \
set_json<T>(path, t); \
QSignalBlocker const blocker(spinner); \
spinner->setValue(t); \
}); \
\
_custom_layout->addRow(label, spinner); \
if(has_slider) _custom_layout->addRow("", slider); \
else slider->hide(); \
_widgets.push_back(label); \
_widgets.push_back(spinner); \
_widgets.push_back(slider); \
set_json<T>(path, std::min(max, std::max(min, get_json_safe<T>(path, def, [](auto json){ return json.is_number();})))); \
auto v = get_json_safe<T>(path, def,[](auto json){ return json.is_number(); }); \
slider->setSliderPosition((int)std::round(v *dp1)); \
spinner->setValue(v);
double script_settings::get_double(std::string const& name)
{
return get_json_unsafe<double>(name);
}
int script_settings::get_int(std::string const& name)
{
return get_json_unsafe<int>(name);
}
bool script_settings::get_bool(std::string const& name)
{
return get_json_unsafe<bool>(name);
}
std::string script_settings::get_string(std::string const& name)
{
return get_json_unsafe<std::string>(name);
}
std::string script_settings::get_string_list(std::string const& name)
{
return get_json_unsafe<std::string>(name);
}
void script_settings::add_double(
std::string const& name
, double min
, double max
, double def
, int zeros
, bool has_slider
){
ADD_SLIDER(name, double, min, max, def, zeros, has_slider);
}
void script_settings::add_int(
std::string const& name
, int min
, int max
, int def
, bool has_slider
){
ADD_SLIDER(name, int, min, max, def, 0, has_slider);
}
void script_settings::add_string(std::string const& name, std::string const& def)
{
auto tline = new QLineEdit(this);
auto label = new QLabel(this);
label->setText(name.c_str());
connect(tline, &QLineEdit::textChanged, this, [=](auto text) {
set_json<std::string>(name, text.toUtf8().constData());
});
_widgets.push_back(label);
_widgets.push_back(tline);
tline->setText(get_json_safe<std::string>(name, def, [](auto json) {return json.is_string(); }).c_str());
_custom_layout->addRow(label, tline);
}
void script_settings::add_bool(std::string const& name, bool def)
{
auto checkbox = new QCheckBox(this);
auto label = new QLabel(this);
label->setText(name.c_str());
connect(checkbox, &QCheckBox::stateChanged, this, [=](auto value) {
set_json<bool>(name, value ? true : false);
});
_widgets.push_back(checkbox);
_widgets.push_back(label);
_custom_layout->addRow(label, checkbox);
checkbox->setCheckState(get_json_safe<bool>(name, def, [](auto json) { return json.is_boolean(); }) ? Qt::CheckState::Checked : Qt::CheckState::Unchecked);
}
void script_settings::add_null(std::string const& text)
{
auto label = new QLabel(this);
label->setText(text.c_str());
_widgets.push_back(label);
_custom_layout->addRow(label);
}
void script_settings::add_string_list(std::string const& name, std::string const& value)
{
if (_string_arrays.find(name) == _string_arrays.end())
{
auto box = new QComboBox(this);
auto label = new QLabel(this);
connect(box, QOverload<int>::of(&QComboBox::activated), this, [=](auto index) {
set_json<std::string>(name, box->itemText(index).toUtf8().constData());
});
box->addItem(value.c_str());
label->setText(name.c_str());
_string_arrays[name] = box;
_widgets.push_back(box);
_widgets.push_back(label);
_custom_layout->addRow(label, box);
// ensure there is at least one valid value in it
get_json_safe<std::string>(name, value, [](auto json) {return json.is_string(); });
}
else
{
auto box = _string_arrays[name];
box->addItem(value.c_str());
// we found the last selection, so change the index for that.
if (get_json_safe<std::string>(name, "", [](auto json) {return json.is_string(); }) == value)
{
box->setCurrentIndex(box->count() - 1);
}
}
}
void script_settings::setOuterRadius(float outerRadius)
{
_radius_spin->setValue(outerRadius);
_radius_slider->setSliderPosition(outerRadius);
set_json (OUTER_RADIUS_PATH, outerRadius);
}
void script_settings::setInnerRadius(float innerRadius)
{
_inner_radius_spin->setValue(innerRadius);
_inner_radius_slider->setSliderPosition(innerRadius*100);
set_json (INNER_RADIUS_PATH, innerRadius);
}
void script_settings::clear()
{
for (auto &widget : _widgets)
{
_custom_layout->removeWidget(widget);
delete widget;
}
_widgets.clear();
_string_arrays.clear();
}
void script_settings::save_json()
{
std::ofstream(SCRIPT_FILE) << std::setw(4) << _json << "\n";
}
void script_settings::load_json()
{
if (!boost::filesystem::exists(SCRIPT_FILE))
{
return;
}
try
{
std::ifstream(SCRIPT_FILE) >> _json;
}
catch (std::exception err)
{
if (!boost::filesystem::exists(SCRIPT_FILE))
{
return;
}
// back up broken script settings, since they won't be read and will be overwritten.
std::string backup_file = std::string(SCRIPT_FILE) + ".backup";
int i = 0;
while (boost::filesystem::exists(backup_file + std::to_string(i)))
{
++i;
}
boost::filesystem::copy(SCRIPT_FILE, backup_file + std::to_string(i));
// Add a message box here
}
}
void script_settings::initialize()
{
double inner_radius = get_json_safe<double>(INNER_RADIUS_PATH, 0.5, [](auto json) {return json.is_number(); });
double outer_radius = get_json_safe<double>(OUTER_RADIUS_PATH, 40, [](auto json) {return json.is_number(); });
_radius_spin->setValue(outer_radius);
_inner_radius_spin->setValue(inner_radius);
_radius_slider->setValue(std::round(outer_radius));
_inner_radius_slider->setSliderPosition((int)std::round(inner_radius * 100));
for (auto& item : _string_arrays)
{
// if the index is 0, that MIGHT mean the value we have
// is invalid (old script), so we just write it again to be safe.
if (item.second->currentIndex() == 0)
{
set_json (item.first, item.second->itemText(0).toStdString());
}
}
}
nlohmann::json * script_settings::get_raw_json()
{
return &_json;
}
tag::tag( script_context * ctx
, std::string const& script
, std::string const& item
)
: script_object(ctx)
, _tool(ctx->tool())
, _script(script)
, _item(item)
{}
int_tag::int_tag(script_context * ctx
, std::string const& script
, std::string const& item
, int min
, int max
, int def
, bool has_slider
)
: tag(ctx,script,item)
, _min(min)
, _max(max)
, _def(def)
, _has_slider(has_slider)
{}
int int_tag::get()
{
return _tool->get_settings()->get_setting<int>(
_script,_tool->get_profiles()->get_cur_profile(),_item,_def);
}
void int_tag::add_to_settings()
{
_tool->get_settings()->add_int(_item, _min,_max,_def);
}
null_tag::null_tag(
script_context * ctx
, std::string const& script
, std::string const& item
, std::string const& text
)
: tag(ctx,script,item)
, _text(text)
{}
void null_tag::add_to_settings()
{
_tool->get_settings()->add_null(_text);
}
real_tag::real_tag(script_context * ctx
, std::string const& script
, std::string const& item
, double min
, double max
, double def
, int zeros
, bool has_slider
)
: tag(ctx,script,item)
, _min(min)
, _max(max)
, _def(def)
, _zeros(zeros)
, _has_slider(has_slider)
{}
double real_tag::get()
{
return _tool->get_settings()->get_setting<double>(
_script,_tool->get_profiles()->get_cur_profile(),_item,_def);
}
void real_tag::add_to_settings()
{
_tool->get_settings()->add_double(_item, _min,_max,_def, _zeros, _has_slider);
}
string_tag::string_tag(script_context * ctx
, std::string const& script
, std::string const& item
, std::string const& def
)
: tag(ctx,script,item)
, _def(def)
{}
std::string string_tag::get()
{
return _tool->get_settings()->get_setting<std::string>(
_script,_tool->get_profiles()->get_cur_profile(),_item,_def);
}
void string_tag::add_to_settings()
{
_tool->get_settings()->add_string(_item ,_def);
}
string_list_tag::string_list_tag(script_context * ctx
, std::string const& script
, std::string const& item
, std::vector<std::string> const& values
)
: tag(ctx,script,item)
, _values(values)
{}
std::string string_list_tag::get()
{
return _tool->get_settings()->get_setting<std::string>(
_script,_tool->get_profiles()->get_cur_profile(),_item,_values[0]);
}
void string_list_tag::add_to_settings()
{
for(auto& val: _values)
{
_tool->get_settings()->add_string_list(_item, val);
}
}
bool_tag::bool_tag(
script_context * ctx
, std::string const& script
, std::string const& item
, bool def
)
: tag(ctx,script,item)
, _def(def)
{}
bool bool_tag::get()
{
return _tool->get_settings()->get_setting<bool>
(
_script,_tool->get_profiles()->get_cur_profile(),_item,_def
);
}
void bool_tag::add_to_settings()
{
_tool->get_settings()->add_bool(_item,_def);
}
void register_settings(script_context * state)
{
state->new_usertype<int_tag>("int_tag","get",&int_tag::get);
state->new_usertype<bool_tag>("bool_tag", "get", &bool_tag::get);
state->new_usertype<real_tag>("real_tag","get",&real_tag::get);
state->new_usertype<string_tag>("string_tag","get",&string_tag::get);
state->new_usertype<string_list_tag>("string_list_tag","get",&string_list_tag::get);
}
} // namespace scripting
} // namespace noggit

View File

@@ -0,0 +1,216 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#pragma once
#include <noggit/scripting/script_object.hpp>
#include <nlohmann/json.hpp>
#include <QtWidgets/QFormLayout>
#include <QtWidgets/QGroupBox>
#include <QtWidgets/QComboBox>
#include <QtWidgets/QCheckBox>
#include <QtWidgets/QVBoxLayout>
#include <QtWidgets/QFormLayout>
#include <QtWidgets/QDoubleSpinBox>
#include <QtWidgets/QSlider>
namespace noggit {
namespace scripting {
class scripting_tool;
class script_profiles;
class script_context;
class script_settings : public QGroupBox {
public:
script_settings(scripting_tool* tool);
void add_double( std::string const& name
, double min
, double max
, double def = 0
, int zeros = 2
, bool has_slider = false
);
void add_int( std::string const& name
, int min
, int max
, int def = 0
, bool has_slider = false
);
void add_bool( std::string const& name, bool def = false);
void add_null( std::string const& text = "");
void add_string(std::string const& name, std::string const& def = "");
void add_string_list(std::string const& name, std::string const& value);
void add_description(std::string const& description);
double get_double(std::string const& name);
int get_int(std::string const& name);
bool get_bool(std::string const& name);
std::string get_string(std::string const& name);
std::string get_string_list(std::string const& name);
float brushRadius() const { return _radius; }
float innerRadius() const { return _inner_radius; }
void setOuterRadius(float outerRadius);
void setInnerRadius(float innerRadius);
void clear();
void save_json();
void load_json();
nlohmann::json * get_raw_json();
template <typename T>
T get_setting(std::string const& script
, std::string const& profile
, std::string const& item
, T def
)
{
if(!_json[script][profile].contains(item))
{
_json[script][profile][item] = def;
return def;
}
return _json[script][profile][item];
}
void initialize();
private:
template <typename T>
T get_json_safe(std::string const& key, T def, std::function<bool(nlohmann::basic_json<>)>);
template <typename T>
T get_json_unsafe(std::string const& key);
template <typename T>
void set_json(std::string const& key, T def);
QGroupBox* _radius_group;
QFormLayout* _radius_layout;
QDoubleSpinBox* _radius_spin;
QSlider* _radius_slider;
QDoubleSpinBox* _inner_radius_spin;
QSlider* _inner_radius_slider;
QVBoxLayout* _layout;
QFrame* _custom_group;
QFormLayout* _custom_layout;
float _radius = 0;
float _inner_radius = 0;
private:
noggit::scripting::scripting_tool* _tool;
std::vector<QWidget*> _widgets;
nlohmann::json _json;
std::map<std::string, QComboBox*> _string_arrays;
};
class tag : public script_object {
public:
tag( script_context * ctx
, std::string const& script
, std::string const& item
);
virtual void add_to_settings() = 0;
protected:
scripting_tool * _tool;
std::string _script;
std::string _item;
private:
};
class int_tag : public tag {
public:
int_tag(script_context * ctx
, std::string const& script
, std::string const& item
, int min
, int max
, int def
, bool has_slider
);
int get();
void set(int value);
virtual void add_to_settings() override;
private:
int _min,_max,_def;
bool _has_slider;
};
class real_tag : public tag {
public:
real_tag( script_context * ctx
, std::string const& script
, std::string const& item
, double min
, double max
, double def
, int zeros
, bool has_slider
);
double get();
virtual void add_to_settings() override;
private:
double _min,_max,_def;
int _zeros;
bool _has_slider;
};
class null_tag : public tag {
public:
null_tag(script_context* ctx
, std::string const& script
, std::string const& item
, std::string const& text = ""
);
virtual void add_to_settings() override;
private:
std::string _text;
};
class string_tag : public tag {
public:
string_tag( script_context * ctx
, std::string const& script
, std::string const& item
, std::string const& def
);
std::string get();
virtual void add_to_settings() override;
private:
std::string _def;
};
class string_list_tag : public tag {
public:
string_list_tag( script_context * ctx
, std::string const& script
, std::string const& item
, std::vector<std::string> const& strings
);
std::string get();
virtual void add_to_settings() override;
private:
std::vector<std::string> _values;
};
class bool_tag : public tag {
public:
bool_tag( script_context * ctx
, std::string const& script
, std::string const& item
, bool def
);
virtual void add_to_settings() override;
bool get();
private:
bool _def;
};
void register_settings(script_context * state);
}
}

View File

@@ -0,0 +1,204 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#include <noggit/scripting/script_standard_brush.hpp>
#include <noggit/scripting/scripting_tool.hpp>
#include <noggit/scripting/script_context.hpp>
#include <noggit/World.h>
#include <noggit/camera.hpp>
#include <noggit/Brush.h>
#include <noggit/ContextObject.hpp>
#include <math/vector_4d.hpp>
#include <sol/sol.hpp>
namespace noggit {
namespace scripting {
standard_brush::standard_brush(script_context * ctx)
: script_object(ctx)
{}
void standard_brush::set_area_id(math::vector_3d const& pos
, int id
, bool adt
)
{
world()->setAreaID(pos, id, adt);
}
void standard_brush::change_vertex_color(
math::vector_3d const& pos
, math::vector_3d const& color
, float alpha
, float change
, float radius
, bool editMode
)
{
auto v = color;
world()->changeShader(
pos, math::vector_4d(v.x, v.y, v.z, alpha), change, radius, editMode);
}
math::vector_3d standard_brush::get_vertex_color(
math::vector_3d const& pos)
{
return world()->pickShaderColor(pos);
}
void standard_brush::flatten_terrain(math::vector_3d const& pos
, float remain
, float radius
, int brush_type
, bool lower
, bool raise
, math::vector_3d const& origin
, double angle
, double orientation
)
{
world()->flattenTerrain( pos
, remain
, radius
, brush_type
, flatten_mode(raise, lower)
, origin
, math::degrees(angle)
, math::degrees(orientation));
}
void standard_brush::blur_terrain(math::vector_3d const& pos
, float remain
, float radius
, int brush_type
, bool lower
, bool raise
)
{
world()->blurTerrain( pos
, remain
, radius
, brush_type
, flatten_mode(raise, lower));
}
void standard_brush::erase_textures(math::vector_3d const& pos)
{
world()->eraseTextures(pos);
}
void standard_brush::clear_shadows(math::vector_3d const& pos)
{
world()->clear_shadows(pos);
}
void standard_brush::clear_textures(math::vector_3d const& pos)
{
world()->clearTextures(pos);
}
void standard_brush::clear_height(math::vector_3d const& pos)
{
world()->clearHeight(pos);
}
void standard_brush::set_hole( math::vector_3d const& pos
, bool big
, bool hole
)
{
world()->setHole(pos, 1.0f, big, hole);
}
void standard_brush::set_hole_adt( math::vector_3d const& pos
, bool hole
)
{
world()->setHoleADT(pos, hole);
}
void standard_brush::update_vertices ()
{
world()->updateVertexCenter();
world()->updateSelectedVertices();
}
void standard_brush::deselect_vertices( math::vector_3d const& pos
, float radius
)
{
world()->deselectVertices(pos, radius);
}
void standard_brush::move_vertices(float h)
{
world()->moveVertices(h);
}
void standard_brush::flatten_vertices(float h)
{
world()->flattenVertices(h);
}
void standard_brush::clear_vertex_selection ()
{
world()->clearVertexSelection();
}
void standard_brush::paint_texture( math::vector_3d const& pos
, float strength
, float pressure
, float hardness
, float radius
, std::string const& texture
)
{
auto brush = Brush();
brush.setHardness(hardness);
brush.setRadius(radius);
world()->paintTexture(pos
, &brush
, strength
, pressure
, scoped_blp_texture_reference(texture, noggit::NoggitRenderContext::MAP_VIEW));
}
void standard_brush::change_terrain( math::vector_3d const& pos
, float change
, float radius
, float inner_radius
, int brush_type
)
{
world()->changeTerrain( pos
, change
, radius
, brush_type
, inner_radius
);
}
void register_standard_brush(script_context * state)
{
state->new_usertype<standard_brush>("standard_brush"
, "change_terrain", &standard_brush::change_terrain
, "set_area_id", &standard_brush::set_area_id
, "change_vertex_color", &standard_brush::change_vertex_color
, "get_vertex_color", &standard_brush::get_vertex_color
, "flatten_terrain", &standard_brush::flatten_terrain
, "blur_terrain", &standard_brush::blur_terrain
, "erase_textures", &standard_brush::erase_textures
, "clear_shadows", &standard_brush::clear_shadows
, "clear_textures", &standard_brush::clear_textures
, "clear_height", &standard_brush::clear_height
, "set_hole", &standard_brush::set_hole
, "set_hole_adt", &standard_brush::set_hole_adt
, "deselect_vertices", &standard_brush::deselect_vertices
, "clear_vertex_selection", &standard_brush::clear_vertex_selection
, "move_vertices", &standard_brush::move_vertices
, "flatten_vertices", &standard_brush::flatten_vertices
, "update_vertices", &standard_brush::update_vertices
, "paint_texture", &standard_brush::paint_texture
);
}
}
}

View File

@@ -0,0 +1,79 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#pragma once
#include <noggit/scripting/script_object.hpp>
#include <math/vector_3d.hpp>
class World;
namespace noggit
{
namespace scripting
{
class scripting_tool;
class script_context;
class standard_brush : public script_object {
public:
standard_brush(script_context * ctx);
void change_terrain(math::vector_3d const&
, float change
, float radius
, float inner_radius
, int brush_type
);
void set_area_id(math::vector_3d const&, int id, bool adt);
void change_vertex_color(math::vector_3d const& pos
, math::vector_3d const& color
, float alpha
, float change
, float radius
, bool editMode
);
math::vector_3d get_vertex_color(math::vector_3d const& pos);
void flatten_terrain(math::vector_3d const& pos
, float remain
, float radius
, int brush_type
, bool lower
, bool raise
, math::vector_3d const& origin
, double angle
, double orientation
);
void blur_terrain(math::vector_3d const& pos
, float remain
, float radius
, int brush_type
, bool lower
, bool raise
);
void erase_textures(math::vector_3d const& pos);
void clear_shadows(math::vector_3d const& pos);
void clear_textures(math::vector_3d const& pos);
void clear_height(math::vector_3d const& pos);
void set_hole(math::vector_3d const& pos, bool big, bool hole);
void set_hole_adt(math::vector_3d const& pos, bool hole);
void deselect_vertices(math::vector_3d const& pos, float radius);
void clear_vertex_selection ();
void move_vertices(float h);
void flatten_vertices(float h);
void update_vertices ();
void paint_texture(math::vector_3d const& pos
, float strength
, float pressure
, float hardness
, float radius
, std::string const& texture
);
};
void register_standard_brush(script_context * state);
} // namespace scripting
} // namespace noggit

View File

@@ -0,0 +1,90 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#include <noggit/scripting/script_tex.hpp>
#include <noggit/MapChunk.h>
#include <noggit/scripting/script_exception.hpp>
#include <noggit/scripting/script_context.hpp>
#include <noggit/scripting/script_math.hpp>
#include <noggit/scripting/script_image.hpp>
#include <sol/sol.hpp>
// amount of texunits per chunk length
#define TEXTURE_UNITS_WIDTH 64
#define TEXTURE_UNITS_PER_CHUNK 4096
namespace noggit {
namespace scripting {
tex::tex(script_context * ctx, MapChunk* chunk, int index)
: script_object(ctx)
, _chunk(chunk)
, _index(index)
{}
float tex::get_alpha(int index)
{
auto& ts = _chunk->texture_set;
ts->create_temporary_alphamaps_if_needed();
return ts->getTempAlphamaps()->get()[index][_index];
}
void tex::set_alpha(int index, float value)
{
if(index<0||index>3)
{
throw script_exception(
"tex_set_alpha",
std::string("invalid texture layer: ")
+ std::to_string(index)
+ std::string(" (in call to tex_set_alpha)")
);
}
auto& ts = _chunk->texture_set;
ts->create_temporary_alphamaps_if_needed();
ts->getTempAlphamaps()->get()[index][_index] = value;
}
namespace {
math::vector_3d tex_location(MapChunk* chnk, int index)
{
float cx = chnk->xbase;
float cz = chnk->zbase;
float x = index % TEXTURE_UNITS_WIDTH;
float z = (float(index) / float(TEXTURE_UNITS_WIDTH));
return math::vector_3d(cx + x * TEXDETAILSIZE, 0, cz + z * TEXDETAILSIZE);
}
}
math::vector_3d tex::get_pos_2d()
{
return tex_location(_chunk, _index);
}
void collect_textures(
script_context * ctx
, MapChunk* chnk
, std::vector<tex>& vec
, math::vector_3d const& min
, math::vector_3d const& max
)
{
for (int i = 0; i < TEXTURE_UNITS_PER_CHUNK; ++i)
{
math::vector_3d loc = tex_location(chnk, i);
if (loc.x >= min.x && loc.x <= max.x && loc.z >= min.z && loc.z <= max.z)
{
vec.emplace_back(ctx, chnk, i);
}
}
}
void register_tex(script_context * state)
{
state->new_usertype<tex>("tex"
, "set_alpha", &tex::set_alpha
, "get_alpha", &tex::get_alpha
, "get_pos_2d", &tex::get_pos_2d
);
}
}
}

View File

@@ -0,0 +1,59 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#pragma once
#include <noggit/scripting/script_object.hpp>
#include <math/vector_3d.hpp>
#include <noggit/scripting/script_image.hpp>
class MapChunk;
namespace noggit {
namespace scripting {
class scripting_tool;
class script_context;
class tex: public script_object
{
public:
tex(script_context * ctx, MapChunk* chunk, int index);
void set_alpha(int index, float alpha);
float get_alpha(int index);
math::vector_3d get_pos_2d();
private:
MapChunk* _chunk;
int _index;
};
void collect_textures(
script_context* ctx
, MapChunk* chnk
, std::vector<tex>& vec
, math::vector_3d const& min
, math::vector_3d const& max
);
class tex_iterator : public script_object {
public:
tex_iterator( script_context * ctx
, std::shared_ptr<std::vector<MapChunk*>> chunks
, math::vector_3d const& min
, math::vector_3d const& max
);
bool next();
tex get();
void paint_image(image & img, int layer, float pressure, float angle);
private:
int _tex_iter = -1;
std::shared_ptr<std::vector<MapChunk*>> _chunks;
std::vector<MapChunk*>::iterator _chunk_iter;
math::vector_3d const& _min;
math::vector_3d const& _max;
};
void register_tex(script_context * state);
}
}

View File

@@ -0,0 +1,160 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
// Note: This file is only a header to clean up script_vert.cpp,
// don't import it anywhere else!
struct TextureIndex
{
short indices[MAX_TEXUNITS_PER_VERT];
};
namespace
{
TextureIndex texture_index[145] = {
TextureIndex{{0, 1, 2, 3, 64, 65, 66, 128, 129, 192, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}},
TextureIndex{{5, 6, 7, 8, 9, 10, 11, 70, 71, 72, 73, 74, 135, 136, 137, 200, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}},
TextureIndex{{13, 14, 15, 16, 17, 18, 19, 78, 79, 80, 81, 82, 143, 144, 145, 208, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}},
TextureIndex{{21, 22, 23, 24, 25, 26, 27, 86, 87, 88, 89, 90, 151, 152, 153, 216, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}},
TextureIndex{{29, 30, 31, 32, 33, 34, 35, 94, 95, 96, 97, 98, 159, 160, 161, 224, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}},
TextureIndex{{37, 38, 39, 40, 41, 42, 43, 102, 103, 104, 105, 106, 167, 168, 169, 232, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}},
TextureIndex{{45, 46, 47, 48, 49, 50, 51, 110, 111, 112, 113, 114, 175, 176, 177, 240, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}},
TextureIndex{{53, 54, 55, 56, 57, 58, 59, 118, 119, 120, 121, 122, 183, 184, 185, 248, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}},
TextureIndex{{61, 62, 63, 126, 127, 191, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}},
TextureIndex{{4, 67, 68, 69, 130, 131, 132, 133, 134, 193, 194, 195, 196, 197, 198, 199, 256, 257, 258, 259, 260, 261, 262, 263, 321, 322, 323, 324, 325, 326, 386, 387, 388, 389, 451, 452}},
TextureIndex{{12, 75, 76, 77, 138, 139, 140, 141, 142, 201, 202, 203, 204, 205, 206, 207, 265, 266, 267, 268, 269, 270, 271, 330, 331, 332, 333, 334, 395, 396, 397, 460, -1, -1, -1, -1}},
TextureIndex{{20, 83, 84, 85, 146, 147, 148, 149, 150, 209, 210, 211, 212, 213, 214, 215, 273, 274, 275, 276, 277, 278, 279, 338, 339, 340, 341, 342, 403, 404, 405, 468, -1, -1, -1, -1}},
TextureIndex{{28, 91, 92, 93, 154, 155, 156, 157, 158, 217, 218, 219, 220, 221, 222, 223, 281, 282, 283, 284, 285, 286, 287, 346, 347, 348, 349, 350, 411, 412, 413, 476, -1, -1, -1, -1}},
TextureIndex{{36, 99, 100, 101, 162, 163, 164, 165, 166, 225, 226, 227, 228, 229, 230, 231, 289, 290, 291, 292, 293, 294, 295, 354, 355, 356, 357, 358, 419, 420, 421, 484, -1, -1, -1, -1}},
TextureIndex{{44, 107, 108, 109, 170, 171, 172, 173, 174, 233, 234, 235, 236, 237, 238, 239, 297, 298, 299, 300, 301, 302, 303, 362, 363, 364, 365, 366, 427, 428, 429, 492, -1, -1, -1, -1}},
TextureIndex{{52, 115, 116, 117, 178, 179, 180, 181, 182, 241, 242, 243, 244, 245, 246, 247, 305, 306, 307, 308, 309, 310, 311, 370, 371, 372, 373, 374, 435, 436, 437, 500, -1, -1, -1, -1}},
TextureIndex{{60, 123, 124, 125, 186, 187, 188, 189, 190, 249, 250, 251, 252, 253, 254, 255, 313, 314, 315, 316, 317, 318, 319, 378, 379, 380, 381, 382, 443, 444, 445, 508, -1, -1, -1, -1}},
TextureIndex{{320, 384, 385, 448, 449, 450, 512, 513, 514, 515, 576, 577, 578, 640, 641, 704, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}},
TextureIndex{{264, 327, 328, 329, 390, 391, 392, 393, 394, 453, 454, 455, 456, 457, 458, 459, 516, 517, 518, 519, 520, 521, 522, 523, 581, 582, 583, 584, 585, 586, 646, 647, 648, 649, 711, 712}},
TextureIndex{{272, 335, 336, 337, 398, 399, 400, 401, 402, 461, 462, 463, 464, 465, 466, 467, 525, 526, 527, 528, 529, 530, 531, 590, 591, 592, 593, 594, 655, 656, 657, 720, -1, -1, -1, -1}},
TextureIndex{{280, 343, 344, 345, 406, 407, 408, 409, 410, 469, 470, 471, 472, 473, 474, 475, 533, 534, 535, 536, 537, 538, 539, 598, 599, 600, 601, 602, 663, 664, 665, 728, -1, -1, -1, -1}},
TextureIndex{{288, 351, 352, 353, 414, 415, 416, 417, 418, 477, 478, 479, 480, 481, 482, 483, 541, 542, 543, 544, 545, 546, 547, 606, 607, 608, 609, 610, 671, 672, 673, 736, -1, -1, -1, -1}},
TextureIndex{{296, 359, 360, 361, 422, 423, 424, 425, 426, 485, 486, 487, 488, 489, 490, 491, 549, 550, 551, 552, 553, 554, 555, 614, 615, 616, 617, 618, 679, 680, 681, 744, -1, -1, -1, -1}},
TextureIndex{{304, 367, 368, 369, 430, 431, 432, 433, 434, 493, 494, 495, 496, 497, 498, 499, 557, 558, 559, 560, 561, 562, 563, 622, 623, 624, 625, 626, 687, 688, 689, 752, -1, -1, -1, -1}},
TextureIndex{{312, 375, 376, 377, 438, 439, 440, 441, 442, 501, 502, 503, 504, 505, 506, 507, 565, 566, 567, 568, 569, 570, 571, 630, 631, 632, 633, 634, 695, 696, 697, 760, -1, -1, -1, -1}},
TextureIndex{{383, 446, 447, 509, 510, 511, 573, 574, 575, 638, 639, 703, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}},
TextureIndex{{579, 580, 642, 643, 644, 645, 705, 706, 707, 708, 709, 710, 768, 769, 770, 771, 772, 773, 774, 775, 833, 834, 835, 836, 837, 838, 898, 899, 900, 901, 963, 964, -1, -1, -1, -1}},
TextureIndex{{524, 587, 588, 589, 650, 651, 652, 653, 654, 713, 714, 715, 716, 717, 718, 719, 776, 777, 778, 779, 780, 781, 782, 783, 841, 842, 843, 844, 845, 846, 906, 907, 908, 909, 971, 972}},
TextureIndex{{532, 595, 596, 597, 658, 659, 660, 661, 662, 721, 722, 723, 724, 725, 726, 727, 785, 786, 787, 788, 789, 790, 791, 850, 851, 852, 853, 854, 915, 916, 917, 980, -1, -1, -1, -1}},
TextureIndex{{540, 603, 604, 605, 666, 667, 668, 669, 670, 729, 730, 731, 732, 733, 734, 735, 793, 794, 795, 796, 797, 798, 799, 858, 859, 860, 861, 862, 923, 924, 925, 988, -1, -1, -1, -1}},
TextureIndex{{548, 611, 612, 613, 674, 675, 676, 677, 678, 737, 738, 739, 740, 741, 742, 743, 801, 802, 803, 804, 805, 806, 807, 866, 867, 868, 869, 870, 931, 932, 933, 996, -1, -1, -1, -1}},
TextureIndex{{556, 619, 620, 621, 682, 683, 684, 685, 686, 745, 746, 747, 748, 749, 750, 751, 809, 810, 811, 812, 813, 814, 815, 874, 875, 876, 877, 878, 939, 940, 941, 1004, -1, -1, -1, -1}},
TextureIndex{{564, 627, 628, 629, 690, 691, 692, 693, 694, 753, 754, 755, 756, 757, 758, 759, 817, 818, 819, 820, 821, 822, 823, 882, 883, 884, 885, 886, 947, 948, 949, 1012, -1, -1, -1, -1}},
TextureIndex{{572, 635, 636, 637, 698, 699, 700, 701, 702, 761, 762, 763, 764, 765, 766, 767, 825, 826, 827, 828, 829, 830, 831, 890, 891, 892, 893, 894, 955, 956, 957, 1020, -1, -1, -1, -1}},
TextureIndex{{832, 896, 897, 960, 961, 962, 1024, 1025, 1026, 1027, 1088, 1089, 1090, 1152, 1153, 1216, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}},
TextureIndex{{839, 840, 902, 903, 904, 905, 965, 966, 967, 968, 969, 970, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1093, 1094, 1095, 1096, 1097, 1098, 1158, 1159, 1160, 1161, 1223, 1224, -1, -1, -1, -1}},
TextureIndex{{784, 847, 848, 849, 910, 911, 912, 913, 914, 973, 974, 975, 976, 977, 978, 979, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1101, 1102, 1103, 1104, 1105, 1106, 1166, 1167, 1168, 1169, 1231, 1232}},
TextureIndex{{792, 855, 856, 857, 918, 919, 920, 921, 922, 981, 982, 983, 984, 985, 986, 987, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1110, 1111, 1112, 1113, 1114, 1175, 1176, 1177, 1240, -1, -1, -1, -1}},
TextureIndex{{800, 863, 864, 865, 926, 927, 928, 929, 930, 989, 990, 991, 992, 993, 994, 995, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1118, 1119, 1120, 1121, 1122, 1183, 1184, 1185, 1248, -1, -1, -1, -1}},
TextureIndex{{808, 871, 872, 873, 934, 935, 936, 937, 938, 997, 998, 999, 1000, 1001, 1002, 1003, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1126, 1127, 1128, 1129, 1130, 1191, 1192, 1193, 1256, -1, -1, -1, -1}},
TextureIndex{{816, 879, 880, 881, 942, 943, 944, 945, 946, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1134, 1135, 1136, 1137, 1138, 1199, 1200, 1201, 1264, -1, -1, -1, -1}},
TextureIndex{{824, 887, 888, 889, 950, 951, 952, 953, 954, 1013, 1014, 1015, 1016, 1017, 1018, 1019, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1142, 1143, 1144, 1145, 1146, 1207, 1208, 1209, 1272, -1, -1, -1, -1}},
TextureIndex{{895, 958, 959, 1021, 1022, 1023, 1085, 1086, 1087, 1150, 1151, 1215, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}},
TextureIndex{{1091, 1092, 1154, 1155, 1156, 1157, 1217, 1218, 1219, 1220, 1221, 1222, 1280, 1281, 1282, 1283, 1284, 1285, 1286, 1287, 1345, 1346, 1347, 1348, 1349, 1350, 1410, 1411, 1412, 1413, 1475, 1476, -1, -1, -1, -1}},
TextureIndex{{1099, 1100, 1162, 1163, 1164, 1165, 1225, 1226, 1227, 1228, 1229, 1230, 1288, 1289, 1290, 1291, 1292, 1293, 1294, 1295, 1353, 1354, 1355, 1356, 1357, 1358, 1418, 1419, 1420, 1421, 1483, 1484, -1, -1, -1, -1}},
TextureIndex{{1044, 1107, 1108, 1109, 1170, 1171, 1172, 1173, 1174, 1233, 1234, 1235, 1236, 1237, 1238, 1239, 1296, 1297, 1298, 1299, 1300, 1301, 1302, 1303, 1361, 1362, 1363, 1364, 1365, 1366, 1426, 1427, 1428, 1429, 1491, 1492}},
TextureIndex{{1052, 1115, 1116, 1117, 1178, 1179, 1180, 1181, 1182, 1241, 1242, 1243, 1244, 1245, 1246, 1247, 1305, 1306, 1307, 1308, 1309, 1310, 1311, 1370, 1371, 1372, 1373, 1374, 1435, 1436, 1437, 1500, -1, -1, -1, -1}},
TextureIndex{{1060, 1123, 1124, 1125, 1186, 1187, 1188, 1189, 1190, 1249, 1250, 1251, 1252, 1253, 1254, 1255, 1313, 1314, 1315, 1316, 1317, 1318, 1319, 1378, 1379, 1380, 1381, 1382, 1443, 1444, 1445, 1508, -1, -1, -1, -1}},
TextureIndex{{1068, 1131, 1132, 1133, 1194, 1195, 1196, 1197, 1198, 1257, 1258, 1259, 1260, 1261, 1262, 1263, 1321, 1322, 1323, 1324, 1325, 1326, 1327, 1386, 1387, 1388, 1389, 1390, 1451, 1452, 1453, 1516, -1, -1, -1, -1}},
TextureIndex{{1076, 1139, 1140, 1141, 1202, 1203, 1204, 1205, 1206, 1265, 1266, 1267, 1268, 1269, 1270, 1271, 1329, 1330, 1331, 1332, 1333, 1334, 1335, 1394, 1395, 1396, 1397, 1398, 1459, 1460, 1461, 1524, -1, -1, -1, -1}},
TextureIndex{{1084, 1147, 1148, 1149, 1210, 1211, 1212, 1213, 1214, 1273, 1274, 1275, 1276, 1277, 1278, 1279, 1337, 1338, 1339, 1340, 1341, 1342, 1343, 1402, 1403, 1404, 1405, 1406, 1467, 1468, 1469, 1532, -1, -1, -1, -1}},
TextureIndex{{1344, 1408, 1409, 1472, 1473, 1474, 1536, 1537, 1538, 1539, 1600, 1601, 1602, 1664, 1665, 1728, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}},
TextureIndex{{1351, 1352, 1414, 1415, 1416, 1417, 1477, 1478, 1479, 1480, 1481, 1482, 1540, 1541, 1542, 1543, 1544, 1545, 1546, 1547, 1605, 1606, 1607, 1608, 1609, 1610, 1670, 1671, 1672, 1673, 1735, 1736, -1, -1, -1, -1}},
TextureIndex{{1359, 1360, 1422, 1423, 1424, 1425, 1485, 1486, 1487, 1488, 1489, 1490, 1548, 1549, 1550, 1551, 1552, 1553, 1554, 1555, 1613, 1614, 1615, 1616, 1617, 1618, 1678, 1679, 1680, 1681, 1743, 1744, -1, -1, -1, -1}},
TextureIndex{{1304, 1367, 1368, 1369, 1430, 1431, 1432, 1433, 1434, 1493, 1494, 1495, 1496, 1497, 1498, 1499, 1556, 1557, 1558, 1559, 1560, 1561, 1562, 1563, 1621, 1622, 1623, 1624, 1625, 1626, 1686, 1687, 1688, 1689, 1751, 1752}},
TextureIndex{{1312, 1375, 1376, 1377, 1438, 1439, 1440, 1441, 1442, 1501, 1502, 1503, 1504, 1505, 1506, 1507, 1565, 1566, 1567, 1568, 1569, 1570, 1571, 1630, 1631, 1632, 1633, 1634, 1695, 1696, 1697, 1760, -1, -1, -1, -1}},
TextureIndex{{1320, 1383, 1384, 1385, 1446, 1447, 1448, 1449, 1450, 1509, 1510, 1511, 1512, 1513, 1514, 1515, 1573, 1574, 1575, 1576, 1577, 1578, 1579, 1638, 1639, 1640, 1641, 1642, 1703, 1704, 1705, 1768, -1, -1, -1, -1}},
TextureIndex{{1328, 1391, 1392, 1393, 1454, 1455, 1456, 1457, 1458, 1517, 1518, 1519, 1520, 1521, 1522, 1523, 1581, 1582, 1583, 1584, 1585, 1586, 1587, 1646, 1647, 1648, 1649, 1650, 1711, 1712, 1713, 1776, -1, -1, -1, -1}},
TextureIndex{{1336, 1399, 1400, 1401, 1462, 1463, 1464, 1465, 1466, 1525, 1526, 1527, 1528, 1529, 1530, 1531, 1589, 1590, 1591, 1592, 1593, 1594, 1595, 1654, 1655, 1656, 1657, 1658, 1719, 1720, 1721, 1784, -1, -1, -1, -1}},
TextureIndex{{1407, 1470, 1471, 1533, 1534, 1535, 1597, 1598, 1599, 1662, 1663, 1727, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}},
TextureIndex{{1603, 1604, 1666, 1667, 1668, 1669, 1729, 1730, 1731, 1732, 1733, 1734, 1792, 1793, 1794, 1795, 1796, 1797, 1798, 1799, 1857, 1858, 1859, 1860, 1861, 1862, 1922, 1923, 1924, 1925, 1987, 1988, -1, -1, -1, -1}},
TextureIndex{{1611, 1612, 1674, 1675, 1676, 1677, 1737, 1738, 1739, 1740, 1741, 1742, 1800, 1801, 1802, 1803, 1804, 1805, 1806, 1807, 1865, 1866, 1867, 1868, 1869, 1870, 1930, 1931, 1932, 1933, 1995, 1996, -1, -1, -1, -1}},
TextureIndex{{1619, 1620, 1682, 1683, 1684, 1685, 1745, 1746, 1747, 1748, 1749, 1750, 1808, 1809, 1810, 1811, 1812, 1813, 1814, 1815, 1873, 1874, 1875, 1876, 1877, 1878, 1938, 1939, 1940, 1941, 2003, 2004, -1, -1, -1, -1}},
TextureIndex{{1564, 1627, 1628, 1629, 1690, 1691, 1692, 1693, 1694, 1753, 1754, 1755, 1756, 1757, 1758, 1759, 1816, 1817, 1818, 1819, 1820, 1821, 1822, 1823, 1881, 1882, 1883, 1884, 1885, 1886, 1946, 1947, 1948, 1949, 2011, 2012}},
TextureIndex{{1572, 1635, 1636, 1637, 1698, 1699, 1700, 1701, 1702, 1761, 1762, 1763, 1764, 1765, 1766, 1767, 1825, 1826, 1827, 1828, 1829, 1830, 1831, 1890, 1891, 1892, 1893, 1894, 1955, 1956, 1957, 2020, -1, -1, -1, -1}},
TextureIndex{{1580, 1643, 1644, 1645, 1706, 1707, 1708, 1709, 1710, 1769, 1770, 1771, 1772, 1773, 1774, 1775, 1833, 1834, 1835, 1836, 1837, 1838, 1839, 1898, 1899, 1900, 1901, 1902, 1963, 1964, 1965, 2028, -1, -1, -1, -1}},
TextureIndex{{1588, 1651, 1652, 1653, 1714, 1715, 1716, 1717, 1718, 1777, 1778, 1779, 1780, 1781, 1782, 1783, 1841, 1842, 1843, 1844, 1845, 1846, 1847, 1906, 1907, 1908, 1909, 1910, 1971, 1972, 1973, 2036, -1, -1, -1, -1}},
TextureIndex{{1596, 1659, 1660, 1661, 1722, 1723, 1724, 1725, 1726, 1785, 1786, 1787, 1788, 1789, 1790, 1791, 1849, 1850, 1851, 1852, 1853, 1854, 1855, 1914, 1915, 1916, 1917, 1918, 1979, 1980, 1981, 2044, -1, -1, -1, -1}},
TextureIndex{{1856, 1920, 1921, 1984, 1985, 1986, 2048, 2049, 2050, 2051, 2112, 2113, 2114, 2176, 2177, 2240, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}},
TextureIndex{{1863, 1864, 1926, 1927, 1928, 1929, 1989, 1990, 1991, 1992, 1993, 1994, 2052, 2053, 2054, 2055, 2056, 2057, 2058, 2059, 2117, 2118, 2119, 2120, 2121, 2122, 2182, 2183, 2184, 2185, 2247, 2248, -1, -1, -1, -1}},
TextureIndex{{1871, 1872, 1934, 1935, 1936, 1937, 1997, 1998, 1999, 2000, 2001, 2002, 2060, 2061, 2062, 2063, 2064, 2065, 2066, 2067, 2125, 2126, 2127, 2128, 2129, 2130, 2190, 2191, 2192, 2193, 2255, 2256, -1, -1, -1, -1}},
TextureIndex{{1879, 1880, 1942, 1943, 1944, 1945, 2005, 2006, 2007, 2008, 2009, 2010, 2068, 2069, 2070, 2071, 2072, 2073, 2074, 2075, 2133, 2134, 2135, 2136, 2137, 2138, 2198, 2199, 2200, 2201, 2263, 2264, -1, -1, -1, -1}},
TextureIndex{{1824, 1887, 1888, 1889, 1950, 1951, 1952, 1953, 1954, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2076, 2077, 2078, 2079, 2080, 2081, 2082, 2083, 2141, 2142, 2143, 2144, 2145, 2146, 2206, 2207, 2208, 2209, 2271, 2272}},
TextureIndex{{1832, 1895, 1896, 1897, 1958, 1959, 1960, 1961, 1962, 2021, 2022, 2023, 2024, 2025, 2026, 2027, 2085, 2086, 2087, 2088, 2089, 2090, 2091, 2150, 2151, 2152, 2153, 2154, 2215, 2216, 2217, 2280, -1, -1, -1, -1}},
TextureIndex{{1840, 1903, 1904, 1905, 1966, 1967, 1968, 1969, 1970, 2029, 2030, 2031, 2032, 2033, 2034, 2035, 2093, 2094, 2095, 2096, 2097, 2098, 2099, 2158, 2159, 2160, 2161, 2162, 2223, 2224, 2225, 2288, -1, -1, -1, -1}},
TextureIndex{{1848, 1911, 1912, 1913, 1974, 1975, 1976, 1977, 1978, 2037, 2038, 2039, 2040, 2041, 2042, 2043, 2101, 2102, 2103, 2104, 2105, 2106, 2107, 2166, 2167, 2168, 2169, 2170, 2231, 2232, 2233, 2296, -1, -1, -1, -1}},
TextureIndex{{1919, 1982, 1983, 2045, 2046, 2047, 2109, 2110, 2111, 2174, 2175, 2239, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}},
TextureIndex{{2115, 2116, 2178, 2179, 2180, 2181, 2241, 2242, 2243, 2244, 2245, 2246, 2304, 2305, 2306, 2307, 2308, 2309, 2310, 2311, 2369, 2370, 2371, 2372, 2373, 2374, 2434, 2435, 2436, 2437, 2499, 2500, -1, -1, -1, -1}},
TextureIndex{{2123, 2124, 2186, 2187, 2188, 2189, 2249, 2250, 2251, 2252, 2253, 2254, 2312, 2313, 2314, 2315, 2316, 2317, 2318, 2319, 2377, 2378, 2379, 2380, 2381, 2382, 2442, 2443, 2444, 2445, 2507, 2508, -1, -1, -1, -1}},
TextureIndex{{2131, 2132, 2194, 2195, 2196, 2197, 2257, 2258, 2259, 2260, 2261, 2262, 2320, 2321, 2322, 2323, 2324, 2325, 2326, 2327, 2385, 2386, 2387, 2388, 2389, 2390, 2450, 2451, 2452, 2453, 2515, 2516, -1, -1, -1, -1}},
TextureIndex{{2139, 2140, 2202, 2203, 2204, 2205, 2265, 2266, 2267, 2268, 2269, 2270, 2328, 2329, 2330, 2331, 2332, 2333, 2334, 2335, 2393, 2394, 2395, 2396, 2397, 2398, 2458, 2459, 2460, 2461, 2523, 2524, -1, -1, -1, -1}},
TextureIndex{{2084, 2147, 2148, 2149, 2210, 2211, 2212, 2213, 2214, 2273, 2274, 2275, 2276, 2277, 2278, 2279, 2336, 2337, 2338, 2339, 2340, 2341, 2342, 2343, 2401, 2402, 2403, 2404, 2405, 2406, 2466, 2467, 2468, 2469, 2531, 2532}},
TextureIndex{{2092, 2155, 2156, 2157, 2218, 2219, 2220, 2221, 2222, 2281, 2282, 2283, 2284, 2285, 2286, 2287, 2345, 2346, 2347, 2348, 2349, 2350, 2351, 2410, 2411, 2412, 2413, 2414, 2475, 2476, 2477, 2540, -1, -1, -1, -1}},
TextureIndex{{2100, 2163, 2164, 2165, 2226, 2227, 2228, 2229, 2230, 2289, 2290, 2291, 2292, 2293, 2294, 2295, 2353, 2354, 2355, 2356, 2357, 2358, 2359, 2418, 2419, 2420, 2421, 2422, 2483, 2484, 2485, 2548, -1, -1, -1, -1}},
TextureIndex{{2108, 2171, 2172, 2173, 2234, 2235, 2236, 2237, 2238, 2297, 2298, 2299, 2300, 2301, 2302, 2303, 2361, 2362, 2363, 2364, 2365, 2366, 2367, 2426, 2427, 2428, 2429, 2430, 2491, 2492, 2493, 2556, -1, -1, -1, -1}},
TextureIndex{{2368, 2432, 2433, 2496, 2497, 2498, 2560, 2561, 2562, 2563, 2624, 2625, 2626, 2688, 2689, 2752, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}},
TextureIndex{{2375, 2376, 2438, 2439, 2440, 2441, 2501, 2502, 2503, 2504, 2505, 2506, 2564, 2565, 2566, 2567, 2568, 2569, 2570, 2571, 2629, 2630, 2631, 2632, 2633, 2634, 2694, 2695, 2696, 2697, 2759, 2760, -1, -1, -1, -1}},
TextureIndex{{2383, 2384, 2446, 2447, 2448, 2449, 2509, 2510, 2511, 2512, 2513, 2514, 2572, 2573, 2574, 2575, 2576, 2577, 2578, 2579, 2637, 2638, 2639, 2640, 2641, 2642, 2702, 2703, 2704, 2705, 2767, 2768, -1, -1, -1, -1}},
TextureIndex{{2391, 2392, 2454, 2455, 2456, 2457, 2517, 2518, 2519, 2520, 2521, 2522, 2580, 2581, 2582, 2583, 2584, 2585, 2586, 2587, 2645, 2646, 2647, 2648, 2649, 2650, 2710, 2711, 2712, 2713, 2775, 2776, -1, -1, -1, -1}},
TextureIndex{{2399, 2400, 2462, 2463, 2464, 2465, 2525, 2526, 2527, 2528, 2529, 2530, 2588, 2589, 2590, 2591, 2592, 2593, 2594, 2595, 2653, 2654, 2655, 2656, 2657, 2658, 2718, 2719, 2720, 2721, 2783, 2784, -1, -1, -1, -1}},
TextureIndex{{2344, 2407, 2408, 2409, 2470, 2471, 2472, 2473, 2474, 2533, 2534, 2535, 2536, 2537, 2538, 2539, 2596, 2597, 2598, 2599, 2600, 2601, 2602, 2603, 2661, 2662, 2663, 2664, 2665, 2666, 2726, 2727, 2728, 2729, 2791, 2792}},
TextureIndex{{2352, 2415, 2416, 2417, 2478, 2479, 2480, 2481, 2482, 2541, 2542, 2543, 2544, 2545, 2546, 2547, 2605, 2606, 2607, 2608, 2609, 2610, 2611, 2670, 2671, 2672, 2673, 2674, 2735, 2736, 2737, 2800, -1, -1, -1, -1}},
TextureIndex{{2360, 2423, 2424, 2425, 2486, 2487, 2488, 2489, 2490, 2549, 2550, 2551, 2552, 2553, 2554, 2555, 2613, 2614, 2615, 2616, 2617, 2618, 2619, 2678, 2679, 2680, 2681, 2682, 2743, 2744, 2745, 2808, -1, -1, -1, -1}},
TextureIndex{{2431, 2494, 2495, 2557, 2558, 2559, 2621, 2622, 2623, 2686, 2687, 2751, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}},
TextureIndex{{2627, 2628, 2690, 2691, 2692, 2693, 2753, 2754, 2755, 2756, 2757, 2758, 2816, 2817, 2818, 2819, 2820, 2821, 2822, 2823, 2881, 2882, 2883, 2884, 2885, 2886, 2946, 2947, 2948, 2949, 3011, 3012, -1, -1, -1, -1}},
TextureIndex{{2635, 2636, 2698, 2699, 2700, 2701, 2761, 2762, 2763, 2764, 2765, 2766, 2824, 2825, 2826, 2827, 2828, 2829, 2830, 2831, 2889, 2890, 2891, 2892, 2893, 2894, 2954, 2955, 2956, 2957, 3019, 3020, -1, -1, -1, -1}},
TextureIndex{{2643, 2644, 2706, 2707, 2708, 2709, 2769, 2770, 2771, 2772, 2773, 2774, 2832, 2833, 2834, 2835, 2836, 2837, 2838, 2839, 2897, 2898, 2899, 2900, 2901, 2902, 2962, 2963, 2964, 2965, 3027, 3028, -1, -1, -1, -1}},
TextureIndex{{2651, 2652, 2714, 2715, 2716, 2717, 2777, 2778, 2779, 2780, 2781, 2782, 2840, 2841, 2842, 2843, 2844, 2845, 2846, 2847, 2905, 2906, 2907, 2908, 2909, 2910, 2970, 2971, 2972, 2973, 3035, 3036, -1, -1, -1, -1}},
TextureIndex{{2659, 2660, 2722, 2723, 2724, 2725, 2785, 2786, 2787, 2788, 2789, 2790, 2848, 2849, 2850, 2851, 2852, 2853, 2854, 2855, 2913, 2914, 2915, 2916, 2917, 2918, 2978, 2979, 2980, 2981, 3043, 3044, -1, -1, -1, -1}},
TextureIndex{{2604, 2667, 2668, 2669, 2730, 2731, 2732, 2733, 2734, 2793, 2794, 2795, 2796, 2797, 2798, 2799, 2856, 2857, 2858, 2859, 2860, 2861, 2862, 2863, 2921, 2922, 2923, 2924, 2925, 2926, 2986, 2987, 2988, 2989, 3051, 3052}},
TextureIndex{{2612, 2675, 2676, 2677, 2738, 2739, 2740, 2741, 2742, 2801, 2802, 2803, 2804, 2805, 2806, 2807, 2865, 2866, 2867, 2868, 2869, 2870, 2871, 2930, 2931, 2932, 2933, 2934, 2995, 2996, 2997, 3060, -1, -1, -1, -1}},
TextureIndex{{2620, 2683, 2684, 2685, 2746, 2747, 2748, 2749, 2750, 2809, 2810, 2811, 2812, 2813, 2814, 2815, 2873, 2874, 2875, 2876, 2877, 2878, 2879, 2938, 2939, 2940, 2941, 2942, 3003, 3004, 3005, 3068, -1, -1, -1, -1}},
TextureIndex{{2880, 2944, 2945, 3008, 3009, 3010, 3072, 3073, 3074, 3075, 3136, 3137, 3138, 3200, 3201, 3264, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}},
TextureIndex{{2887, 2888, 2950, 2951, 2952, 2953, 3013, 3014, 3015, 3016, 3017, 3018, 3076, 3077, 3078, 3079, 3080, 3081, 3082, 3083, 3141, 3142, 3143, 3144, 3145, 3146, 3206, 3207, 3208, 3209, 3271, 3272, -1, -1, -1, -1}},
TextureIndex{{2895, 2896, 2958, 2959, 2960, 2961, 3021, 3022, 3023, 3024, 3025, 3026, 3084, 3085, 3086, 3087, 3088, 3089, 3090, 3091, 3149, 3150, 3151, 3152, 3153, 3154, 3214, 3215, 3216, 3217, 3279, 3280, -1, -1, -1, -1}},
TextureIndex{{2903, 2904, 2966, 2967, 2968, 2969, 3029, 3030, 3031, 3032, 3033, 3034, 3092, 3093, 3094, 3095, 3096, 3097, 3098, 3099, 3157, 3158, 3159, 3160, 3161, 3162, 3222, 3223, 3224, 3225, 3287, 3288, -1, -1, -1, -1}},
TextureIndex{{2911, 2912, 2974, 2975, 2976, 2977, 3037, 3038, 3039, 3040, 3041, 3042, 3100, 3101, 3102, 3103, 3104, 3105, 3106, 3107, 3165, 3166, 3167, 3168, 3169, 3170, 3230, 3231, 3232, 3233, 3295, 3296, -1, -1, -1, -1}},
TextureIndex{{2919, 2920, 2982, 2983, 2984, 2985, 3045, 3046, 3047, 3048, 3049, 3050, 3108, 3109, 3110, 3111, 3112, 3113, 3114, 3115, 3173, 3174, 3175, 3176, 3177, 3178, 3238, 3239, 3240, 3241, 3303, 3304, -1, -1, -1, -1}},
TextureIndex{{2864, 2927, 2928, 2929, 2990, 2991, 2992, 2993, 2994, 3053, 3054, 3055, 3056, 3057, 3058, 3059, 3116, 3117, 3118, 3119, 3120, 3121, 3122, 3123, 3181, 3182, 3183, 3184, 3185, 3186, 3246, 3247, 3248, 3249, 3311, 3312}},
TextureIndex{{2872, 2935, 2936, 2937, 2998, 2999, 3000, 3001, 3002, 3061, 3062, 3063, 3064, 3065, 3066, 3067, 3125, 3126, 3127, 3128, 3129, 3130, 3131, 3190, 3191, 3192, 3193, 3194, 3255, 3256, 3257, 3320, -1, -1, -1, -1}},
TextureIndex{{2943, 3006, 3007, 3069, 3070, 3071, 3133, 3134, 3135, 3198, 3199, 3263, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}},
TextureIndex{{3139, 3140, 3202, 3203, 3204, 3205, 3265, 3266, 3267, 3268, 3269, 3270, 3328, 3329, 3330, 3331, 3332, 3333, 3334, 3335, 3393, 3394, 3395, 3396, 3397, 3398, 3458, 3459, 3460, 3461, 3523, 3524, -1, -1, -1, -1}},
TextureIndex{{3147, 3148, 3210, 3211, 3212, 3213, 3273, 3274, 3275, 3276, 3277, 3278, 3336, 3337, 3338, 3339, 3340, 3341, 3342, 3343, 3401, 3402, 3403, 3404, 3405, 3406, 3466, 3467, 3468, 3469, 3531, 3532, -1, -1, -1, -1}},
TextureIndex{{3155, 3156, 3218, 3219, 3220, 3221, 3281, 3282, 3283, 3284, 3285, 3286, 3344, 3345, 3346, 3347, 3348, 3349, 3350, 3351, 3409, 3410, 3411, 3412, 3413, 3414, 3474, 3475, 3476, 3477, 3539, 3540, -1, -1, -1, -1}},
TextureIndex{{3163, 3164, 3226, 3227, 3228, 3229, 3289, 3290, 3291, 3292, 3293, 3294, 3352, 3353, 3354, 3355, 3356, 3357, 3358, 3359, 3417, 3418, 3419, 3420, 3421, 3422, 3482, 3483, 3484, 3485, 3547, 3548, -1, -1, -1, -1}},
TextureIndex{{3171, 3172, 3234, 3235, 3236, 3237, 3297, 3298, 3299, 3300, 3301, 3302, 3360, 3361, 3362, 3363, 3364, 3365, 3366, 3367, 3425, 3426, 3427, 3428, 3429, 3430, 3490, 3491, 3492, 3493, 3555, 3556, -1, -1, -1, -1}},
TextureIndex{{3179, 3180, 3242, 3243, 3244, 3245, 3305, 3306, 3307, 3308, 3309, 3310, 3368, 3369, 3370, 3371, 3372, 3373, 3374, 3375, 3433, 3434, 3435, 3436, 3437, 3438, 3498, 3499, 3500, 3501, 3563, 3564, -1, -1, -1, -1}},
TextureIndex{{3124, 3187, 3188, 3189, 3250, 3251, 3252, 3253, 3254, 3313, 3314, 3315, 3316, 3317, 3318, 3319, 3376, 3377, 3378, 3379, 3380, 3381, 3382, 3383, 3441, 3442, 3443, 3444, 3445, 3446, 3506, 3507, 3508, 3509, 3571, 3572}},
TextureIndex{{3132, 3195, 3196, 3197, 3258, 3259, 3260, 3261, 3262, 3321, 3322, 3323, 3324, 3325, 3326, 3327, 3385, 3386, 3387, 3388, 3389, 3390, 3391, 3450, 3451, 3452, 3453, 3454, 3515, 3516, 3517, 3580, -1, -1, -1, -1}},
TextureIndex{{3392, 3456, 3457, 3520, 3521, 3522, 3584, 3585, 3586, 3587, 3648, 3649, 3650, 3712, 3713, 3776, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}},
TextureIndex{{3399, 3400, 3462, 3463, 3464, 3465, 3525, 3526, 3527, 3528, 3529, 3530, 3588, 3589, 3590, 3591, 3592, 3593, 3594, 3595, 3653, 3654, 3655, 3656, 3657, 3658, 3718, 3719, 3720, 3721, 3783, 3784, -1, -1, -1, -1}},
TextureIndex{{3407, 3408, 3470, 3471, 3472, 3473, 3533, 3534, 3535, 3536, 3537, 3538, 3596, 3597, 3598, 3599, 3600, 3601, 3602, 3603, 3661, 3662, 3663, 3664, 3665, 3666, 3726, 3727, 3728, 3729, 3791, 3792, -1, -1, -1, -1}},
TextureIndex{{3415, 3416, 3478, 3479, 3480, 3481, 3541, 3542, 3543, 3544, 3545, 3546, 3604, 3605, 3606, 3607, 3608, 3609, 3610, 3611, 3669, 3670, 3671, 3672, 3673, 3674, 3734, 3735, 3736, 3737, 3799, 3800, -1, -1, -1, -1}},
TextureIndex{{3423, 3424, 3486, 3487, 3488, 3489, 3549, 3550, 3551, 3552, 3553, 3554, 3612, 3613, 3614, 3615, 3616, 3617, 3618, 3619, 3677, 3678, 3679, 3680, 3681, 3682, 3742, 3743, 3744, 3745, 3807, 3808, -1, -1, -1, -1}},
TextureIndex{{3431, 3432, 3494, 3495, 3496, 3497, 3557, 3558, 3559, 3560, 3561, 3562, 3620, 3621, 3622, 3623, 3624, 3625, 3626, 3627, 3685, 3686, 3687, 3688, 3689, 3690, 3750, 3751, 3752, 3753, 3815, 3816, -1, -1, -1, -1}},
TextureIndex{{3439, 3440, 3502, 3503, 3504, 3505, 3565, 3566, 3567, 3568, 3569, 3570, 3628, 3629, 3630, 3631, 3632, 3633, 3634, 3635, 3693, 3694, 3695, 3696, 3697, 3698, 3758, 3759, 3760, 3761, 3823, 3824, -1, -1, -1, -1}},
TextureIndex{{3384, 3447, 3448, 3449, 3510, 3511, 3512, 3513, 3514, 3573, 3574, 3575, 3576, 3577, 3578, 3579, 3636, 3637, 3638, 3639, 3640, 3641, 3642, 3643, 3701, 3702, 3703, 3704, 3705, 3706, 3766, 3767, 3768, 3769, 3831, 3832}},
TextureIndex{{3455, 3518, 3519, 3581, 3582, 3583, 3645, 3646, 3647, 3710, 3711, 3775, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}},
TextureIndex{{3651, 3652, 3714, 3715, 3716, 3717, 3777, 3778, 3779, 3780, 3781, 3782, 3840, 3841, 3842, 3843, 3844, 3845, 3846, 3847, 3905, 3906, 3907, 3908, 3909, 3910, 3970, 3971, 3972, 3973, 4035, 4036, -1, -1, -1, -1}},
TextureIndex{{3659, 3660, 3722, 3723, 3724, 3725, 3785, 3786, 3787, 3788, 3789, 3790, 3848, 3849, 3850, 3851, 3852, 3853, 3854, 3855, 3913, 3914, 3915, 3916, 3917, 3918, 3978, 3979, 3980, 3981, 4043, 4044, -1, -1, -1, -1}},
TextureIndex{{3667, 3668, 3730, 3731, 3732, 3733, 3793, 3794, 3795, 3796, 3797, 3798, 3856, 3857, 3858, 3859, 3860, 3861, 3862, 3863, 3921, 3922, 3923, 3924, 3925, 3926, 3986, 3987, 3988, 3989, 4051, 4052, -1, -1, -1, -1}},
TextureIndex{{3675, 3676, 3738, 3739, 3740, 3741, 3801, 3802, 3803, 3804, 3805, 3806, 3864, 3865, 3866, 3867, 3868, 3869, 3870, 3871, 3929, 3930, 3931, 3932, 3933, 3934, 3994, 3995, 3996, 3997, 4059, 4060, -1, -1, -1, -1}},
TextureIndex{{3683, 3684, 3746, 3747, 3748, 3749, 3809, 3810, 3811, 3812, 3813, 3814, 3872, 3873, 3874, 3875, 3876, 3877, 3878, 3879, 3937, 3938, 3939, 3940, 3941, 3942, 4002, 4003, 4004, 4005, 4067, 4068, -1, -1, -1, -1}},
TextureIndex{{3691, 3692, 3754, 3755, 3756, 3757, 3817, 3818, 3819, 3820, 3821, 3822, 3880, 3881, 3882, 3883, 3884, 3885, 3886, 3887, 3945, 3946, 3947, 3948, 3949, 3950, 4010, 4011, 4012, 4013, 4075, 4076, -1, -1, -1, -1}},
TextureIndex{{3699, 3700, 3762, 3763, 3764, 3765, 3825, 3826, 3827, 3828, 3829, 3830, 3888, 3889, 3890, 3891, 3892, 3893, 3894, 3895, 3953, 3954, 3955, 3956, 3957, 3958, 4018, 4019, 4020, 4021, 4083, 4084, -1, -1, -1, -1}},
TextureIndex{{3644, 3707, 3708, 3709, 3770, 3771, 3772, 3773, 3774, 3833, 3834, 3835, 3836, 3837, 3838, 3839, 3896, 3897, 3898, 3899, 3900, 3901, 3902, 3903, 3961, 3962, 3963, 3964, 3965, 3966, 4026, 4027, 4028, 4029, 4091, 4092}},
TextureIndex{{3904, 3968, 3969, 4032, 4033, 4034, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}},
TextureIndex{{3911, 3912, 3974, 3975, 3976, 3977, 4037, 4038, 4039, 4040, 4041, 4042, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}},
TextureIndex{{3919, 3920, 3982, 3983, 3984, 3985, 4045, 4046, 4047, 4048, 4049, 4050, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}},
TextureIndex{{3927, 3928, 3990, 3991, 3992, 3993, 4053, 4054, 4055, 4056, 4057, 4058, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}},
TextureIndex{{3935, 3936, 3998, 3999, 4000, 4001, 4061, 4062, 4063, 4064, 4065, 4066, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}},
TextureIndex{{3943, 3944, 4006, 4007, 4008, 4009, 4069, 4070, 4071, 4072, 4073, 4074, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}},
TextureIndex{{3951, 3952, 4014, 4015, 4016, 4017, 4077, 4078, 4079, 4080, 4081, 4082, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}},
TextureIndex{{3959, 3960, 4022, 4023, 4024, 4025, 4085, 4086, 4087, 4088, 4089, 4090, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}},
TextureIndex{{3967, 4030, 4031, 4093, 4094, 4095, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}},
};
}

View File

@@ -0,0 +1,180 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#include <noggit/scripting/script_vert.hpp>
#include <noggit/scripting/script_exception.hpp>
#include <noggit/scripting/script_context.hpp>
#include <noggit/scripting/scripting_tool.hpp>
#include <sol/sol.hpp>
#include <vector>
// maximum amount of texunits that can be closest to a vertex
#define MAX_TEXUNITS_PER_VERT 36
// total amount of vertices in each pair of two rows
#define VERTS_PER_TWO_ROWS 17
// maximum vertex index on odd rows
#define VERTS_ON_ODD_ROWS 8
#include <noggit/scripting/script_vert-script_texture_index.ipp>
namespace noggit
{
namespace scripting
{
vert::vert(script_context * ctx, MapChunk* chunk, int index)
: script_object(ctx)
, _chunk(chunk)
, _index(index)
{
}
void vert::set_height(float value)
{
_chunk->mVertices[_index].y = value;
}
void vert::add_height(float value)
{
_chunk->mVertices[_index].y += value;
}
void vert::sub_height(float value)
{
_chunk->mVertices[_index].y -= value;
}
void vert::set_color(float r, float g, float b)
{
// todo create MCCV
_chunk->mccv[_index] = math::vector_3d(r, g, b);
}
math::vector_3d vert::get_color()
{
if (!_chunk->hasColors())
{
return math::vector_3d(1, 1, 1);
}
else
{
return math::vector_3d(_chunk->mccv[_index]);
}
}
void vert::set_water(int type, float height)
{
if (is_water_aligned())
{
return;
}
// TODO: Extremely inefficient
_chunk->liquid_chunk()->paintLiquid(get_pos(), 1, type, true, math::radians(0), math::radians(0), true, math::vector_3d(0, height, 0), true, true, _chunk, 1);
}
void vert::set_hole(bool add)
{
_chunk->setHole(get_pos(), 1.f, false, add);
}
math::vector_3d vert::get_pos()
{
return _chunk->mVertices[_index];
}
void vert::set_alpha(int index, float alpha)
{
if(index<0||index>3)
{
throw script_exception(
"vert::set_alpha",
std::string("invalid texture layer: ")
+ std::to_string(index));
}
if (index == 0)
{
return;
}
auto& ts = _chunk->texture_set;
ts->create_temporary_alphamaps_if_needed();
auto tex_indices = texture_index[_index];
for ( auto iter = std::begin(tex_indices.indices)
; iter != std::end(tex_indices.indices)
; ++iter
)
{
if (*iter == -1)
break;
ts->getTempAlphamaps()->get()[index][*iter] = alpha;
}
}
float vert::get_alpha(int index)
{
if(index<0||index>3)
{
throw script_exception(
"vert::get_alpha",
std::string("invalid texture layer: ")
+ std::to_string(index));
}
if (index == 0)
{
return 1;
}
auto& ts = _chunk->texture_set;
ts->create_temporary_alphamaps_if_needed();
auto tex_indices = texture_index[_index];
float sum = 0;
int ctr = 0;
for (auto iter = std::begin(tex_indices.indices)
; iter != std::end(tex_indices.indices)
; ++iter
)
{
if (*iter == -1)
break;
sum += ts->getTempAlphamaps()->get()[index][*iter];
++ctr;
}
return sum / float(ctr);
}
bool vert::is_water_aligned()
{
return (_index % VERTS_PER_TWO_ROWS) > VERTS_ON_ODD_ROWS;
}
sol::as_table_t<std::vector<tex>> vert::textures()
{
std::vector<tex> texVec;
for (int i = 0; i < MAX_TEXUNITS_PER_VERT; ++i)
{
if (texture_index[_index].indices[i] == -1) break;
texVec.emplace_back(state(), _chunk, texture_index[_index].indices[i]);
}
return sol::as_table(texVec);
}
void register_vert(script_context * state)
{
state->new_usertype<vert>("vert"
, "get_pos", &vert::get_pos
, "set_height", &vert::set_height
, "add_height", &vert::add_height
, "sub_height", &vert::sub_height
, "set_color", &vert::set_color
, "get_color", &vert::get_color
, "set_water", &vert::set_water
, "set_hole", &vert::set_hole
, "set_alpha", &vert::set_alpha
, "get_alpha", &vert::get_alpha
, "tex", &vert::textures
, "is_water_aligned", &vert::is_water_aligned
);
}
} // namespace scripting
} // namespace noggit

View File

@@ -0,0 +1,42 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#pragma once
#include <noggit/scripting/script_tex.hpp>
#include <noggit/scripting/script_object.hpp>
#include <noggit/MapChunk.h>
#include <math/vector_3d.hpp>
namespace noggit
{
namespace scripting
{
class scripting_tool;
class script_context;
class vert: public script_object
{
public:
vert(script_context * ctx, MapChunk* chunk, int index);
math::vector_3d get_pos();
void set_height(float y);
void add_height(float y);
void sub_height(float y);
math::vector_3d get_color();
void set_color(float r, float g, float b);
void set_water(int type, float height);
void set_hole(bool add);
void set_alpha(int index, float alpha);
float get_alpha(int index);
sol::as_table_t<std::vector<tex>> textures();
bool is_water_aligned();
private:
MapChunk* _chunk;
int _index;
};
void register_vert(script_context * state);
} // namespace scripting
} // namespace noggit

View File

@@ -0,0 +1,324 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#include <noggit/scripting/script_context.hpp>
#include <noggit/scripting/script_exception.hpp>
#include <noggit/scripting/script_profiles.hpp>
#include <noggit/scripting/script_settings.hpp>
#include <noggit/scripting/scripting_tool.hpp>
#include <noggit/camera.hpp>
#include <noggit/Log.h>
#include <noggit/tool_enums.hpp>
#include <noggit/World.h>
#include <noggit/MapView.h>
#include <QtWidgets/QFormLayout>
#include <QtWidgets/QDoubleSpinBox>
#include <QtWidgets/QSlider>
#include <QtWidgets/QGroupBox>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QScrollBar>
#include <QtWidgets/QCheckBox>
#include <boost/filesystem.hpp>
#include <boost/thread.hpp>
#include <cmath>
#define CUR_PROFILE_PATH "__cur_profile"
namespace noggit
{
namespace scripting
{
// TEMP: remove when exceptions are working
namespace
{
std::string cur_exception = "";
}
void set_cur_exception(std::string const& exception)
{
cur_exception = exception;
}
void scripting_tool::doReload()
{
get_settings()->clear();
clearLog();
int old_selection = -1;
try
{
std::string old_name = get_context() == nullptr ? "" : get_context()->get_selected_name();
_script_context = std::make_unique<script_context>(this);
for(int i=0;i<get_context()->get_scripts().size(); ++i)
{
if(get_context()->get_scripts()[i]->get_name() == old_name)
{
old_selection = i;
break;
}
}
// default to 0 if there are entries
if(get_context()->get_scripts().size()>0 && old_selection < 0)
{
old_selection = 0;
}
}
catch (std::exception const& e)
{
addLog("[error]: " + std::string(e.what()));
resetLogScroll();
return;
}
_selection->clear();
for(auto& script : get_context()->get_scripts())
{
_selection->addItem(script->get_name().c_str());
}
if (old_selection >= 0)
{
_selection->setCurrentIndex(old_selection);
change_script(old_selection);
}
}
void scripting_tool::change_script(int selection)
{
std::lock_guard<std::mutex> const lock (_script_change_mutex);
clearDescription();
get_settings()->clear();
auto sn = _script_context->get_scripts()[selection]->get_name();
get_profiles()->clear();
auto json = get_settings()->get_raw_json();
if (json->contains(sn))
{
std::vector<std::string> items;
for (auto& v : (*json)[sn].items())
{
if (v.key() != CUR_PROFILE_PATH)
{
items.push_back(v.key());
}
}
std::sort(items.begin(), items.end(), [](auto a, auto b) {
if (a == "Default")
return true;
if (b == "Default")
return false;
return a < b;
});
for (auto& item : items)
{
get_profiles()->add_profile(item);
}
}
if (get_profiles()->profile_count() == 0)
{
get_profiles()->add_profile("Default");
}
int next_profile = 0;
auto cur_script = get_context()->get_scripts()[selection]->get_name();
if (json->contains(cur_script))
{
if ((*json)[cur_script].contains(CUR_PROFILE_PATH))
{
auto str = (*json)[cur_script][CUR_PROFILE_PATH].get<std::string>();
for (int i = 0; i < get_profiles()->profile_count(); ++i)
{
if (get_profiles()->get_profile(i) == str)
{
next_profile = i;
break;
}
}
}
}
get_profiles()->select_profile(next_profile);
try {
get_context()->select_script(selection);
} catch(script_exception const& err)
{
addLog(err.what());
}
get_settings()->initialize();
}
scripting_tool::scripting_tool(
QWidget* parent
, MapView* view
, QSettings* noggit_settings
)
: QWidget(parent)
, _cur_profile ("Default")
, _view(view)
, _noggit_settings(noggit_settings)
{
auto layout(new QVBoxLayout(this));
layout->setContentsMargins(0, 1, 0, 1);
_selection = new QComboBox();
layout->addWidget(_selection);
_reload_button = new QPushButton("Reload Scripts", this);
layout->addWidget(_reload_button);
connect(_reload_button, &QPushButton::released, this, [this]() {
doReload();
});
_profiles = new script_profiles(this);
layout->addWidget(_profiles);
_settings = new script_settings(this);
_settings->load_json();
layout->addWidget(_settings);
_description = new QLabel(this);
layout->addWidget(_description);
_log = new QPlainTextEdit(this);
_log->setFont (QFontDatabase::systemFont (QFontDatabase::FixedFont));
_log->setReadOnly(true);
layout->addWidget(_log);
connect(_selection
, QOverload<int>::of(&QComboBox::activated)
, this
, [this](auto index)
{
clearLog();
change_script(index);
});
doReload();
}
scripting_tool::~scripting_tool()
{
get_settings()->save_json();
}
void scripting_tool::sendBrushEvent(math::vector_3d const& pos, float dt)
{
bool new_left = get_view()->leftMouse;
bool new_right = get_view()->rightMouse;
auto evt = std::make_shared<script_brush_event>(
get_settings()
, pos
, dt
);
try
{
int sel = get_context()->get_selection();
if(sel>=0)
{
auto brush = get_context()->get_scripts()[sel];
if(new_left)
{
if(!_last_left ) brush->on_left_click.call_if_exists("brush_event",evt);
else brush->on_left_hold.call_if_exists("brush_event",evt);
}
else
{
if(_last_left) brush->on_left_release.call_if_exists("(brush_event)",evt);
}
if(new_right)
{
if(!_last_right) brush->on_right_click.call_if_exists("brush_event",evt);
else brush->on_right_hold.call_if_exists("brush_event",evt);
}
else
{
if(_last_right) brush->on_right_release.call_if_exists("(brush_event)",evt);
}
}
}
catch (std::exception const& e)
{
doReload();
// TEMP: remove when exceptions are working
if(std::string(e.what()).find("C++ exception") == 0 && cur_exception.size()>0)
{
addLog("[error]: "+std::string(cur_exception));
cur_exception = "";
}
else
{
addLog(("[error]: " + std::string(e.what())));
}
resetLogScroll();
}
_last_left = new_left;
_last_right = new_right;
}
void scripting_tool::addDescription(std::string const& stext)
{
_description->setText(_description->text()
+ "\n"
+ QString::fromStdString (stext)
);
}
void scripting_tool::addLog(std::string const& text)
{
LogDebug << "[script window]: " << text << "\n";
_log->appendPlainText (QString::fromStdString (text));
_log->verticalScrollBar()->setValue(_log->verticalScrollBar()->maximum());
}
script_context* scripting_tool::get_context()
{
return _script_context.get();
}
MapView* scripting_tool::get_view()
{
return _view;
}
void scripting_tool::resetLogScroll()
{
_log->verticalScrollBar()->setValue(0);
}
void scripting_tool::clearLog()
{
_log->clear();
}
void scripting_tool::clearDescription()
{
_description->clear();
}
script_settings* scripting_tool::get_settings()
{
return _settings;
}
script_profiles* scripting_tool::get_profiles()
{
return _profiles;
}
QSettings* scripting_tool::get_noggit_settings()
{
return _noggit_settings;
}
} // namespace scripting
} // namespace noggit

View File

@@ -0,0 +1,86 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#pragma once
#include <noggit/scripting/script_context.hpp>
#include <noggit/scripting/script_brush.hpp>
#include <noggit/tool_enums.hpp>
#include <math/trig.hpp>
#include <math/vector_3d.hpp>
#include <QtWidgets/QWidget>
#include <QtWidgets/QComboBox>
#include <QtWidgets/QLabel>
#include <QtWidgets/QPlainTextEdit>
#include <QtWidgets/QDoubleSpinBox>
#include <QtWidgets/QLineEdit>
#include <QtWidgets/QGroupBox>
#include <QtWidgets/QFormLayout>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QGridLayout>
#include <QSettings>
#include <map>
#include <mutex>
class World;
class MapView;
namespace noggit
{
class camera;
namespace scripting
{
class script_context;
class script_settings;
class script_profiles;
class scripting_tool : public QWidget
{
public:
scripting_tool(QWidget* parent
, MapView* view
, QSettings * noggit_settings
);
~scripting_tool();
void addDescription(std::string const& text);
void clearDescription();
void addLog(std::string const& text);
void resetLogScroll();
void clearLog();
void doReload();
void sendBrushEvent(math::vector_3d const& pos,float dt);
MapView* get_view();
script_context* get_context();
script_settings* get_settings();
script_profiles* get_profiles();
QSettings* get_noggit_settings();
private:
std::mutex _script_change_mutex;
std::string _cur_profile;
bool _last_left = false;
bool _last_right = false;
private:
QComboBox* _selection;
QPushButton* _reload_button;
QLabel* _description;
QPlainTextEdit* _log;
script_settings* _settings;
script_profiles* _profiles;
private:
std::unique_ptr<script_context> _script_context = nullptr;
MapView* _view;
QSettings * _noggit_settings;
void change_script(int script_index);
};
// TEMP: remove when exceptions are working
void set_cur_exception(std::string const& exception);
} // namespace scripting
} // namespace noggit

View File

@@ -944,19 +944,13 @@ void TextureSet::change_texture_flag(scoped_blp_texture_reference const& tex, st
{
if (textures[i] == tex)
{
if (add)
{
// override the current speed/rotation
if (flag & 0x3F)
{
_layers_info[i].flags &= ~0x3F;
}
_layers_info[i].flags |= flag;
}
else
{
_layers_info[i].flags &= ~flag;
}
auto flag_view = reinterpret_cast<MCLYFlags*>(&_layers_info[i].flags);
auto flag_view_new = reinterpret_cast<MCLYFlags*>(&flag);
flag_view->animation_speed = flag_view_new->animation_speed;
flag_view->animation_rotation = flag_view_new->animation_rotation;
flag_view->animation_enabled = flag_view_new->animation_enabled;
if (flag & FLAG_GLOW)
{
@@ -970,6 +964,8 @@ void TextureSet::change_texture_flag(scoped_blp_texture_reference const& tex, st
break;
}
}
_chunk->registerChunkUpdate(ChunkUpdateFlags::FLAGS);
}
std::vector<std::vector<uint8_t>> TextureSet::save_alpha(bool big_alphamap)
@@ -1255,25 +1251,10 @@ namespace
}
}
/*
std::vector<uint8_t> TextureSet::lod_texture_map()
{
// make sure all changes have been applied
apply_alpha_changes();
if (_need_lod_texture_map_update)
{
update_lod_texture_map();
}
return _lod_texture_map;
}
*/
void TextureSet::update_lod_texture_map()
{
std::vector<std::uint8_t> lod;
std::array<std::uint16_t, 8> lod;
for (std::size_t z = 0; z < 8; ++z)
{
@@ -1288,11 +1269,11 @@ void TextureSet::update_lod_texture_map()
++dominant_square_count[max_element_index (current_layer_values (nTextures, alphamaps.data(), pz, px))];
}
}
lod.push_back (max_element_index (dominant_square_count));
//lod.push_back (max_element_index (dominant_square_count));
}
}
//_lod_texture_map = lod;
_doodadMapping = lod;
_need_lod_texture_map_update = false;
}
@@ -1392,4 +1373,23 @@ void TextureSet::markDirty()
{
_chunk->registerChunkUpdate(ChunkUpdateFlags::ALPHAMAP);
_need_lod_texture_map_update = true;
}
void TextureSet::setEffect(size_t id, int value)
{
_layers_info[id].effectID = value;
_chunk->registerChunkUpdate(ChunkUpdateFlags::FLAGS);
}
std::array<std::uint16_t, 8> TextureSet::lod_texture_map()
{
// make sure all changes have been applied
apply_alpha_changes();
if (_need_lod_texture_map_update)
{
update_lod_texture_map();
}
return _doodadMapping;
}

View File

@@ -85,6 +85,10 @@ public:
void markDirty();
void setEffect(size_t id, int value);
std::array<std::uint16_t, 8> lod_texture_map();
std::array<boost::optional<Alphamap>, 3>* getAlphamaps() { return &alphamaps; };
boost::optional<tmp_edit_alpha_values>* getTempAlphamaps() { return &tmp_edit_values; };

View File

@@ -73,7 +73,8 @@ enum class editing_mode
object = 8,
minimap = 9,
stamp = 10,
light = 11
light = 11,
scripting = 12
};
enum water_opacity

View File

@@ -26,6 +26,7 @@ namespace noggit
add_tool_icon (editing_mode::minimap, tr("Minimap Editor"), font_noggit::TOOL_MINIMAP_EDITOR);
add_tool_icon(editing_mode::stamp, tr("Stamp Mode"), font_noggit::TOOL_STAMP);
add_tool_icon(editing_mode::light, tr("Light Editor"), font_noggit::TOOL_STAMP);
add_tool_icon (editing_mode::scripting, tr("Scripting"), font_noggit::INFO);
}
void toolbar::add_tool_icon(editing_mode mode, const QString& name, const font_noggit::icons& icon)

View File

@@ -555,8 +555,9 @@ namespace noggit
void texturing_tool::change_tex_flag(World* world, math::vector_3d const& pos, bool add, scoped_blp_texture_reference texture)
{
std::size_t flag = 0;
std::uint32_t flag = 0;
auto flag_view = reinterpret_cast<MCLYFlags*>(&flag);
flag |= FLAG_ANIMATE;
@@ -564,13 +565,9 @@ namespace noggit
if (add)
{
// the qdial in inverted compared to the anim rotation
flag |= (_anim_rotation_prop.get() + 4) % 8;
flag |= _anim_speed_prop.get() << 3;
flag_view->animation_rotation = (_anim_rotation_prop.get() + 4) % 8;
flag_view->animation_speed = _anim_speed_prop.get();
}
else
{
flag |= 0xF;
}
// the texture's flag glow is set if the property is true, removed otherwise
if (_overbright_prop.get())

View File

@@ -1051,7 +1051,7 @@ template void opengl::context::bufferSubData<GL_ARRAY_BUFFER>(GLuint buffer, GLi
void opengl::context::drawElements (GLenum mode, GLuint index_buffer, GLsizei count, GLenum type, GLvoid const* indices)
{
GLuint old;
gl.getIntegerv (GL_ELEMENT_ARRAY_BUFFER, reinterpret_cast<GLint*>(&old));
gl.getIntegerv (GL_ELEMENT_ARRAY_BUFFER_BINDING, reinterpret_cast<GLint*>(&old));
gl.bindBuffer (GL_ELEMENT_ARRAY_BUFFER, index_buffer);
drawElements (mode, count, type, indices);
gl.bindBuffer (GL_ELEMENT_ARRAY_BUFFER, old);

View File

@@ -59,11 +59,11 @@ namespace opengl
int ChunkTextureSamplers[4];
int ChunkTextureArrayIDs[4];
int ChunkHoles_DrawImpass_TexLayerCount_CantPaint[4];
math::vector_4d ChunkTexAnim_0_1;
math::vector_4d ChunkTexAnim_2_3;
math::vector_4d AreaIDColor_DrawSelection;
math::vector_4d pad1;
math::vector_4d pad2;
int ChunkTexDoAnim[4];
int ChunkTexAnimSpeed[4];
int AreaIDColor_Pad2_DrawSelection[4];
math::vector_4d ChunkXYZBase_Pad1;
int ChunkTexAnimDir[4];
};
}

9
src/util/visit.hpp Normal file
View File

@@ -0,0 +1,9 @@
#pragma once
namespace util
{
template <typename Variant, typename... Funs>
auto visit (Variant& variant, Funs... funs);
}
#include <util/visit.ipp>

41
src/util/visit.ipp Normal file
View File

@@ -0,0 +1,41 @@
#include <boost/variant/variant.hpp>
#include <type_traits>
namespace util
{
namespace detail
{
template<typename... Ts>
struct require_all_same;
template<typename T, typename... Ts>
struct require_all_same<T, T, Ts...> : require_all_same<T, Ts...> {};
template<typename T>
struct require_all_same<T> { using type = T; };
template<typename Variant, typename Fun>
struct require_all_results_same_for_variant_apply;
template<typename... VariantTypes, typename Fun>
struct require_all_results_same_for_variant_apply<boost::variant<VariantTypes...>, Fun>
: require_all_same<std::result_of_t<Fun (VariantTypes)>...> {};
}
template <typename Variant, typename... Funs>
auto visit (Variant& variant, Funs... funs)
{
struct only_inherit_funs : Funs... {
using Funs::operator()...;
};
using Ret = typename detail::require_all_results_same_for_variant_apply<std::remove_const_t<Variant>, only_inherit_funs>::type;
struct lambda_visitor : boost::static_visitor<Ret>, Funs...
{
using Funs::operator()...;
lambda_visitor (Funs... funs)
: Funs (funs)...
{}
} visitor = {funs...};
return boost::apply_visitor (visitor, variant);
}
}