Remove old map editor

Removes the old map editor and files that only it depended on.
This commit is contained in:
Stephen E. Baker
2016-02-09 19:31:20 -05:00
parent 6ad4cad18c
commit 1156f4054b
38 changed files with 0 additions and 5725 deletions

17
.gitattributes vendored
View File

@@ -15,7 +15,6 @@ CorsixTH/Bitmap/flag_travel_east.bmp -text
CorsixTH/Bitmap/flag_travel_north.bmp -text
CorsixTH/Bitmap/flag_travel_south.bmp -text
CorsixTH/Bitmap/flag_travel_west.bmp -text
CorsixTH/Bitmap/flags32.png -text
CorsixTH/Bitmap/fullscreen_border_bottom.bmp -text
CorsixTH/Bitmap/fullscreen_border_bottomleft.bmp -text
CorsixTH/Bitmap/fullscreen_border_bottomright.bmp -text
@@ -32,13 +31,6 @@ CorsixTH/Bitmap/map_cell_outline_east.bmp -text
CorsixTH/Bitmap/map_cell_outline_north.bmp -text
CorsixTH/Bitmap/map_cell_outline_south.bmp -text
CorsixTH/Bitmap/map_cell_outline_west.bmp -text
CorsixTH/Bitmap/new32.png -text svneol=unset#image/png
CorsixTH/Bitmap/open32.png -text svneol=unset#image/png
CorsixTH/Bitmap/parcels32.png -text
CorsixTH/Bitmap/positions32.png -text
CorsixTH/Bitmap/redo32.png -text
CorsixTH/Bitmap/save32.png -text svneol=unset#image/png
CorsixTH/Bitmap/transparent_walls32.png -text
CorsixTH/Bitmap/tree_collapsed.bmp -text
CorsixTH/Bitmap/tree_ctrl.dat -text
CorsixTH/Bitmap/tree_ctrl.pal -text
@@ -46,7 +38,6 @@ CorsixTH/Bitmap/tree_ctrl.tab -text
CorsixTH/Bitmap/tree_expanded.bmp -text
CorsixTH/Bitmap/tree_leaf.bmp -text
CorsixTH/Bitmap/tree_level.bmp -text
CorsixTH/Bitmap/undo32.png -text
CorsixTH/CorsixTH.ico -text
CorsixTH/Icon.icns -text
CorsixTH/Levels/Example.map -text
@@ -54,11 +45,6 @@ CorsixTH/Levels/avatar.map -text
CorsixTH/Levels/confined_v5.map -text
CorsixTH/Levels/finisham.map -text
CorsixTH/Levels/original08.level -text
CorsixTH/Lua/command.lua -text
CorsixTH/Lua/command_stack.lua -text
CorsixTH/Lua/commands/compound.lua -text
CorsixTH/Lua/commands/set_map_cell.lua -text
CorsixTH/Lua/commands/set_map_cell_flags.lua -text
CorsixTH/Lua/dialogs/resizables/customise.lua -text
CorsixTH/Lua/dialogs/resizables/folder_settings.lua -text
CorsixTH/Lua/dialogs/resizables/update.lua -text
@@ -104,7 +90,4 @@ LevelEdit/src/icon256.png -text
LevelEdit/src/icon32.png -text
LevelEdit/src/icon48.png -text
LevelEdit/src/icon64.png -text
MapEdit/Icon.icns -text
MapEdit/MapEdit.ico -text
MapEdit/RequiredResources.txt -text
WindowsInstaller/welcome.bmp -text

View File

@@ -7,7 +7,6 @@
# - WITH_FREETYPE2
# - WITH_MOVIES : Activate movies (requires Sound)
# - BUILD_ANIMVIEWER
# - BUILD_MAPEDITOR
# - WITH_LUAJIT : Whether to use LuaJIT 2 instead of Lua51 (default is LuaJIT 2)
# - WITH_LIBAV : Whether to use LibAV (as opposed to FFMEPG) when building movies
# - WITH_VLD : Build with Visual Leak Detector (requires Visual Studio)
@@ -37,7 +36,6 @@ OPTION(WITH_FREETYPE2 "Enhanced Font Support" ON)
OPTION(WITH_LUAJIT "Use LuaJIT instead of Lua" OFF)
OPTION(WITH_LIBAV "Use LibAV instead of FFmpeg" OFF)
OPTION(BUILD_ANIMVIEWER "Build the animation viewer as part of the build process" OFF)
OPTION(BUILD_MAPEDITOR "Build the map editor as part of the build process" OFF)
IF(MSVC)
OPTION(WITH_VLD "Build with Visual Leak Detector for Visual Studio" OFF)
ENDIF(MSVC)
@@ -107,15 +105,6 @@ IF(BUILD_ANIMVIEWER)
add_subdirectory(AnimView)
ENDIF(BUILD_ANIMVIEWER)
IF(BUILD_MAPEDITOR)
IF(WITH_OPENGL)
message("Building MapEdit")
add_subdirectory(MapEdit)
ELSE(WITH_OPENGL)
message(FATAL_ERROR "The map editor can only be built when using OpenGL as renderer")
ENDIF(WITH_OPENGL)
ENDIF(BUILD_MAPEDITOR)
# Documentation generation, construct 'doc' target (or a message it is disabled).
# Try to find 'lua'
@@ -172,14 +161,6 @@ IF (DOXYGEN_FOUND)
add_dependencies(doc doc_leveledit)
add_custom_target(doc_mapedit
${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/DoxyGen/mapedit.doxygen
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc
COMMENT "Generating API documentation for MapEdit" VERBATIM
)
add_dependencies(doc doc_mapedit)
add_custom_target(doc_corsixth_engine
${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/DoxyGen/corsixth_engine.doxygen
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc
@@ -223,7 +204,6 @@ IF (DOXYGEN_FOUND)
file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/doc/index.html "<ul>\n")
file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/doc/index.html " <li><a href=\"animview/html/index.html\">Animation viewer documentation</a>\n")
file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/doc/index.html " <li><a href=\"leveledit/html/index.html\">Level editor documentation</a>\n")
file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/doc/index.html " <li><a href=\"mapedit/html/index.html\">Map editor documentation</a>\n")
ENDIF (DOXYGEN_FOUND)
IF (DOXYGEN_FOUND OR LUA_PROGRAM_FOUND)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 342 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1008 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 413 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 890 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 353 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -1,29 +0,0 @@
--[[ Copyright (c) 2013 Alan Woolley
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. --]]
class "Command"
---@type Command
local Command = _G["Command"]
function Command:Command(can_undo)
self.can_undo = can_undo
end

View File

@@ -1,61 +0,0 @@
--[[ Copyright (c) 2013 Alan Woolley
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. --]]
class "CommandStack"
---@type CommandStack
local CommandStack = _G["CommandStack"]
function CommandStack:CommandStack()
self.undo_stack = {}
self.redo_stack = {}
end
function CommandStack:redo()
if (#self.redo_stack == 0) then
print "Nothing left to redo!"
return
end
local cmd = self.redo_stack[#self.redo_stack]
table.remove(self.redo_stack, #self.redo_stack)
table.insert(self.undo_stack, #self.undo_stack + 1, cmd)
cmd:perform()
return #self.redo_stack == 0
end
function CommandStack:undo()
if (#self.undo_stack == 0) then
print "Nothing left to undo!"
return
end
local cmd = self.undo_stack[#self.undo_stack]
table.remove(self.undo_stack, #self.undo_stack)
table.insert(self.redo_stack, #self.redo_stack + 1, cmd)
cmd:undo()
return #self.undo_stack == 0
end
function CommandStack:add(cmd)
if not cmd.can_undo then
self.undo_stack = {}
end
self.redo_stack = {}
table.insert(self.undo_stack, #self.undo_stack + 1, cmd)
end

View File

@@ -1,48 +0,0 @@
--[[ Copyright (c) 2013 Alan Woolley
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. --]]
class "CompoundCommand" (Command)
---@type CompoundCommand
local CompoundCommand = _G["CompoundCommand"]
function CompoundCommand:CompoundCommand()
self:Command(true)
self.command_list = {}
end
function CompoundCommand:addCommand(cmd)
table.insert(self.command_list, #self.command_list + 1, cmd)
end
function CompoundCommand:perform()
for i = 1 , #self.command_list do
local cmd = self.command_list[i]
cmd:perform()
end
end
function CompoundCommand:undo()
for i = #self.command_list, 1, -1 do
local cmd = self.command_list[i]
cmd:undo()
end
end

View File

@@ -1,50 +0,0 @@
--[[ Copyright (c) 2013 Alan Woolley
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. --]]
class "SetMapCellCommand" (Command)
---@type SetMapCellCommand
local SetMapCellCommand = _G["SetMapCellCommand"]
function SetMapCellCommand:SetMapCellCommand(map)
self:Command(true)
self.map = map
self.paint_list = {}
end
function SetMapCellCommand:addTile(x_tile, y_tile, ...)
local old = {self.map:getCell(x_tile, y_tile)}
table.insert(self.paint_list, #self.paint_list + 1, {x = x_tile, y = y_tile, new_flags = {...}, old_flags = old})
end
function SetMapCellCommand:perform()
for i = 1 , #self.paint_list do
local cell_table = self.paint_list[i]
self.map:setCell(cell_table.x, cell_table.y, unpack(cell_table.new_flags))
end
end
function SetMapCellCommand:undo()
for i = #self.paint_list, 1, -1 do
local cell_table = self.paint_list[i]
self.map:setCell(cell_table.x, cell_table.y, unpack(cell_table.old_flags))
end
end

View File

@@ -1,49 +0,0 @@
--[[ Copyright (c) 2013 Alan Woolley
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. --]]
class "SetMapCellFlagsCommand" (Command)
---@type SetMapCellFlagsCommand
local SetMapCellFlagsCommand = _G["SetMapCellFlagsCommand"]
function SetMapCellFlagsCommand:SetMapCellFlagsCommand(map)
self:Command(true)
self.map = map
self.paint_list = {}
end
function SetMapCellFlagsCommand:addTile(x_tile, y_tile, ...)
local old = {self.map:getCellFlags(x_tile, y_tile)}
table.insert(self.paint_list, #self.paint_list + 1, {x = x_tile, y = y_tile, new_flags = {...}, old_flags = old})
end
function SetMapCellFlagsCommand:perform()
for i = 1 , #self.paint_list do
local cell_table = self.paint_list[i]
self.map:setCellFlags(cell_table.x, cell_table.y, unpack(cell_table.new_flags))
end
end
function SetMapCellFlagsCommand:undo()
for i = #self.paint_list, 1, -1 do
local cell_table = self.paint_list[i]
self.map:setCellFlags(cell_table.x, cell_table.y, unpack(cell_table.old_flags))
end
end

View File

@@ -146,9 +146,6 @@ int CorsixTH_lua_main_no_eval(lua_State *L)
#if defined(IS_CORSIXTH_APP)
"code = loadfile(\"CorsixTH.app/Contents/Resources/\"..name)\n"
"if code then return code end\n"
#elif defined(IS_MAPEDIT_APP)
"code = loadfile(\"MapEdit.app/Contents/Resources/\"..name)\n"
"if code then return code end\n"
#endif
#endif
"for num_dotdot = 0, 3 do\n"

File diff suppressed because it is too large Load Diff

View File

@@ -1,200 +0,0 @@
# Project Declaration
PROJECT(MapEdit)
# 2.8.3 is required for the wxWidgets finder to know about ribbon
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.3)
# Generate source files list
# Note: Done after generating config.h
INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR}/CorsixTH/Src/)
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/CorsixTH/Src/)
FILE(GLOB_RECURSE mapedit_source_files
${CMAKE_SOURCE_DIR}/MapEdit/Src/*.cpp
${CMAKE_SOURCE_DIR}/MapEdit/Src/*.c
${CMAKE_SOURCE_DIR}/MapEdit/Src/*.h
${CMAKE_SOURCE_DIR}/MapEdit/MapEdit.rc
${CMAKE_SOURCE_DIR}/CorsixTH/Src/*.h
${CMAKE_SOURCE_DIR}/CorsixTH/Src/*.c
${CMAKE_SOURCE_DIR}/CorsixTH/Src/*.cpp
${CMAKE_SOURCE_DIR}/LFS/*.c
${CMAKE_SOURCE_DIR}/LPEG/*.c
)
# Declaration of the executable
IF(APPLE)
add_definitions(-DIS_MAPEDIT_APP)
set(corsixth_icon_file ${CMAKE_SOURCE_DIR}/MapEdit/Icon.icns)
set_source_files_properties(
${corsixth_icon_file}
PROPERTIES
MACOSX_PACKAGE_LOCATION Resources
)
set(MACOSX_BUNDLE_ICON_FILE Icon.icns)
add_executable(MapEdit
MACOSX_BUNDLE
${mapedit_source_files}
${corsixth_icon_file}
)
set_target_properties(MapEdit PROPERTIES LINK_FLAGS_MINSIZEREL "-dead_strip")
set_target_properties(MapEdit PROPERTIES XCODE_ATTRIBUTE_LD_RUNPATH_SEARCH_PATHS "@executable_path/../Frameworks")
#Add an extra step at the end of the build process to copy the resources into the bundle.
add_custom_command(TARGET MapEdit
POST_BUILD
COMMAND rsync -rv --include-from ${CMAKE_SOURCE_DIR}/MapEdit/RequiredResources.txt ${CMAKE_SOURCE_DIR}/CorsixTH/ \${TARGET_BUILD_DIR}/\${FULL_PRODUCT_NAME}/Contents/Resources)
ELSE()
add_executable(MapEdit
WIN32
${mapedit_source_files}
)
ENDIF()
# Basic platform dependant stuff
IF(UNIX)
IF(APPLE)
# fruit goes here
ELSE(APPLE)
# regular unix/linux
ENDIF(APPLE)
ELSE(UNIX)
IF(WIN32)
# Win32 specific
IF(MSVC)
# We want to bind against the very latest versions of the MSVC runtimes
add_definitions(/D "_BIND_TO_CURRENT_VCLIBS_VERSION=1")
ELSE(MSVC)
IF(MSYS)
# MSYS stuff
ELSE(MSYS)
# What's left? MINGW? CYGWIN? BORLAND?
ENDIF(MSYS)
ENDIF(MSVC)
ELSE(WIN32)
# other OS (not UNIX, not 32/64 bit Windows)
ENDIF(WIN32)
ENDIF(UNIX)
# Finding libraries
# Find WxWidgets
SET(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${PROJECT_SOURCE_DIR}")
MESSAGE("Module path: ${CMAKE_MODULE_PATH}")
SET(wxWidgets_USE_LIBS gl ribbon core base) # optionally: more than wx std libs
FIND_PACKAGE(wxWidgets REQUIRED)
IF(wxWidgets_FOUND)
LINK_LIBRARIES(${wxWidgets_LIBRARIES})
INCLUDE_DIRECTORIES(${wxWidgets_INCLUDE_DIRS})
INCLUDE(${wxWidgets_USE_FILE})
TARGET_LINK_LIBRARIES(MapEdit ${wxWidgets_LIBRARIES})
message(" wxWidgets found")
ELSE(wxWidgets_FOUND)
message( FATAL_ERROR "error: wxWdigets library (or one of it's components) not found, it is required to build")
message( "Make sure the path is correctly defined or set the envirnomental variable WXWIN to the correct location" )
ENDIF(wxWidgets_FOUND)
# Find SDL
FIND_PACKAGE(SDL2 REQUIRED)
IF(SDL_FOUND)
INCLUDE_DIRECTORIES(${SDL_INCLUDE_DIR})
TARGET_LINK_LIBRARIES(MapEdit ${SDL_LIBRARY})
message( " SDL found" )
ELSE(SDL_FOUND)
message( FATAL_ERROR "error: SDL library not found, it is required to build")
message( "Make sure the path is correctly defined or set the envirnomental variable SDLDIR to the correct location" )
ENDIF(SDL_FOUND)
# Find SDL_mixer
IF(CORSIX_TH_USE_SDL_MIXER)
FIND_PACKAGE(SDL2_mixer REQUIRED)
IF(SDLMIXER_FOUND)
TARGET_LINK_LIBRARIES(MapEdit ${SDLMIXER_LIBRARY})
INCLUDE_DIRECTORIES(${SDLMIXER_INCLUDE_DIR})
message( " SDL_mixer found" )
ELSE(SDLMIXER_FOUND)
message( "error: SDL_mixer library not found, it was selected to be included")
ENDIF(SDLMIXER_FOUND)
ENDIF(CORSIX_TH_USE_SDL_MIXER)
# Find FFMPEG
IF(CORSIX_TH_USE_FFMPEG)
FIND_PACKAGE(FFmpeg COMPONENTS AVFORMAT AVCODEC AVUTIL SWSCALE SWRESAMPLE REQUIRED)
IF(FFMPEG_FOUND)
TARGET_LINK_LIBRARIES(MapEdit ${FFMPEG_LIBRARIES})
INCLUDE_DIRECTORIES(${FFMPEG_INCLUDE_DIRS})
IF(APPLE)
TARGET_LINK_LIBRARIES(MapEdit libz.dylib)
ENDIF()
message(" FFmpeg found")
ELSE(FFMPEG_FOUND)
message("Error: FFmpeg library not found, even though it was selected to be included")
ENDIF(FFMPEG_FOUND)
ENDIF(CORSIX_TH_USE_FFMPEG)
# Find Freetype2
IF(CORSIX_TH_USE_FREETYPE2)
FIND_PACKAGE(Freetype REQUIRED)
IF(FREETYPE_FOUND)
TARGET_LINK_LIBRARIES(MapEdit ${FREETYPE_LIBRARIES})
INCLUDE_DIRECTORIES(${FREETYPE_INCLUDE_DIRS})
IF(APPLE)
TARGET_LINK_LIBRARIES(MapEdit libz.dylib)
TARGET_LINK_LIBRARIES(MapEdit libbz2.dylib)
ENDIF()
message(" FreeType2 found")
ELSE(FREETYPE_FOUND)
message("Error: FreeType2 library not found, even though it was selected to be used")
ENDIF(FREETYPE_FOUND)
ENDIF(CORSIX_TH_USE_FREETYPE2)
# Find OpenGL
IF(CORSIX_TH_USE_OGL_RENDERER)
FIND_PACKAGE(OpenGL REQUIRED)
IF(OPENGL_FOUND)
TARGET_LINK_LIBRARIES( MapEdit ${OPENGL_gl_LIBRARY})
INCLUDE_DIRECTORIES(${OPENGL_INCLUDE_DIR})
message( " OpenGL found" )
ELSE(OPENGL_FOUND)
message( FATAL_ERROR "error: OpenGL library not found, it is required to build")
ENDIF(OPENGL_FOUND)
ENDIF(CORSIX_TH_USE_OGL_RENDERER)
# Find Lua
FIND_PACKAGE(Lua REQUIRED)
IF(Lua_FOUND)
TARGET_LINK_LIBRARIES(MapEdit ${LUA_LIBRARY})
INCLUDE_DIRECTORIES(${LUA_INCLUDE_DIR})
# Special link flags needed on OSX/64bit, according to: http://luajit.org/install.html
# If these are not specified, luaL_newstate() returns NULL and we get this:
# Fatal error starting CorsixTH: Cannot open Lua state.
IF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND LUA_INTERPRETER_TYPE STREQUAL "LuaJIT" AND CMAKE_SIZEOF_VOID_P EQUAL 8)
TARGET_LINK_LIBRARIES(MapEdit "-pagezero_size 10000" "-image_base 100000000")
ENDIF()
message(" ${LUA_INTERPRETER_TYPE} found")
ELSE(Lua_FOUND)
message(FATAL_ERROR "Error: Lua library not found, it is required to build")
ENDIF(Lua_FOUND)
# Find msinttypes for MSVC
IF(MSVC AND NOT CORSIX_TH_HAS_INTTYPES_H)
FIND_PATH(MSINTTYPES_INCLUDE_DIRS "inttypes.h" NO_DEFAULT_PATH)
MESSAGE(STATUS "Adding include directory: ${MSINTTYPES_INCLUDE_DIRS}")
INCLUDE_DIRECTORIES(${MSINTTYPES_INCLUDE_DIRS})
SET(CORSIX_TH_HAS_INTTYPES_H 1)
ENDIF(MSVC AND NOT CORSIX_TH_HAS_INTTYPES_H)
IF(APPLE)
#Just use the prefix as it's sufficient to just set the prefix to /Applications on Mac.
install(TARGETS MapEdit BUNDLE DESTINATION .)
# Fix the OS X bundle to include required libraries (create a redistributable app)
install(CODE "
INCLUDE(BundleUtilities)
SET(BU_CHMOD_BUNDLE_ITEMS ON)
FIXUP_BUNDLE(${CMAKE_INSTALL_PREFIX}/MapEdit.app \"\" \"\")
")
ELSE()
install(TARGETS MapEdit RUNTIME DESTINATION CorsixTH)
ENDIF()

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 KiB

View File

@@ -1,34 +0,0 @@
// Microsoft Visual C++ generated resource script.
//
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.K.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
#pragma code_page(1252)
#endif //_WIN32
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_MAPEDIT ICON "MapEdit.ico"
#endif // English (U.K.) resources
/////////////////////////////////////////////////////////////////////////////

View File

@@ -1,14 +0,0 @@
# rsync compatible filter file which is used post-build
# to help with copying the required resources into the
# bundles for the Mac build.
- .svn
- .DS_Store
- CVS
+ CorsixTH.lua
+ Lua/
+ Lua/**
+ Bitmap/
+ Bitmap/*.png
+ Bitmap/aux_ui.*
- *

View File

@@ -1,38 +0,0 @@
/*
Copyright (c) 2009 Peter "Corsix" Cawley
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "app.h"
//Darrell: This macro has to be called before the frmMain.h include otherwise
//a subsequent SDL include causes main() to be replaced with SDLmain().
IMPLEMENT_APP(ThemeHospitalMapEditApp)
#include "frmMain.h"
bool ThemeHospitalMapEditApp::OnInit()
{
wxImage::AddHandler(new wxPNGHandler);
wxTopLevelWindow *pForm = new frmMain;
pForm->Show(true);
SetTopWindow(pForm);
return true;
}

View File

@@ -1,47 +0,0 @@
/*
Copyright (c) 2009 Peter "Corsix" Cawley
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once
// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
// for all others, include the necessary headers (this file is usually all you
// need because it includes almost all "standard" wxWidgets headers)
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
// ----------------------------
#include <wx/glcanvas.h>
#ifndef wxUSE_GLCANVAS
#error To compile the map editor, wxWidgets must be compiled with OpenGL
#endif
class ThemeHospitalMapEditApp : public wxGLApp
{
virtual bool OnInit();
};
DECLARE_APP(ThemeHospitalMapEditApp)

View File

@@ -1,286 +0,0 @@
/*
Copyright (c) 2009 Peter "Corsix" Cawley
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "block_gallery.h"
#include <map>
BEGIN_EVENT_TABLE(RibbonBlockGallery, wxRibbonGallery)
EVT_BUTTON(wxID_ANY, RibbonBlockGallery::OnExtButton)
END_EVENT_TABLE()
RibbonBlockGallery::RibbonBlockGallery(wxWindow* parent, wxWindowID id)
: wxRibbonGallery(parent, id)
{
}
RibbonBlockGallery::~RibbonBlockGallery()
{
_clearCategories();
}
#define FOREACH(container_t, itr_name, container_name) \
for(container_t::iterator itr_name = container_name.begin(), \
itr_name##_end = container_name.end(); itr_name != itr_name##_end; \
++itr_name)
void RibbonBlockGallery::_clearCategories()
{
FOREACH(categorylist_t, itr, m_vCategories)
{
Unbind(wxEVT_COMMAND_MENU_SELECTED,
&RibbonBlockGallery::OnToggleCategory, this, (**itr).iID);
delete *itr;
}
m_vCategories.clear();
}
void RibbonBlockGallery::Populate(THSpriteSheet *pBlocks,
const char* sCategory,
const char* sSubCategory,
lua_State* L,
int iInfoIndex)
{
m_vBlocks.clear();
_clearCategories();
typedef std::map<wxString, category_t*> category_map_t;
category_map_t mapCategories;
// Extract relevant block information from Lua
if(LUA_REGISTRYINDEX < iInfoIndex && iInfoIndex < 0)
iInfoIndex = lua_gettop(L) + 1 + iInfoIndex;
lua_pushstring(L, sCategory);
int iCategoryIndex = lua_gettop(L);
lua_pushstring(L, sSubCategory);
lua_pushnil(L);
int iBaseIndex = lua_gettop(L);
while(lua_next(L, iInfoIndex) != 0)
{
lua_rawgeti(L, -1, 1);
if(lua_equal(L, -1, iCategoryIndex))
{
lua_pop(L, 1);
lua_rawgeti(L, -1, 2);
if(lua_equal(L, -1, iCategoryIndex + 1))
{
lua_pop(L, 1);
block_t oBlock;
oBlock.iBlock = lua_tointeger(L, -2);
oBlock.iBaseBlock = 0;
wxString sCategory(L"Miscellaneous");
lua_rawgeti(L, -1, 3);
if(lua_type(L, -1) == LUA_TSTRING)
sCategory = lua_tostring(L, -1);
oBlock.pCategory = mapCategories[sCategory];
if(oBlock.pCategory == NULL)
{
oBlock.pCategory = new category_t;
oBlock.pCategory->bEnabled = true;
oBlock.pCategory->sName = sCategory;
oBlock.pCategory->iID = wxID_HIGHEST + 1 +
mapCategories.size();
Bind(wxEVT_COMMAND_MENU_SELECTED,
&RibbonBlockGallery::OnToggleCategory, this,
oBlock.pCategory->iID);
mapCategories[sCategory] = oBlock.pCategory;
}
lua_pop(L, 1);
lua_getfield(L, -1, "base");
if(lua_type(L, -1) == LUA_TNUMBER)
oBlock.iBaseBlock = lua_tointeger(L, -1);
lua_pop(L, 1);
m_vBlocks.push_back(oBlock);
}
}
lua_settop(L, iBaseIndex);
}
lua_pop(L, 2);
FOREACH(category_map_t, itr, mapCategories)
{
m_vCategories.push_back(itr->second);
}
// Load block bitmaps
wxSize szLargestBitmap(0, 0);
FOREACH(blocklist_t, itr, m_vBlocks)
{
unsigned int iWidth, iHeight;
if(!pBlocks->getSpriteSize(itr->iBlock, &iWidth, &iHeight))
continue;
wxImage imgBlock(iWidth, iHeight);
if(!imgBlock.HasAlpha())
imgBlock.InitAlpha();
pBlocks->wxDrawSprite(itr->iBlock, imgBlock.GetData(), imgBlock.GetAlpha());
_trimImage(imgBlock);
if(imgBlock.GetWidth() > szLargestBitmap.GetWidth())
szLargestBitmap.SetWidth(imgBlock.GetWidth());
if(imgBlock.GetHeight() > szLargestBitmap.GetHeight())
szLargestBitmap.SetHeight(imgBlock.GetHeight());
itr->bmpTrimmed = wxBitmap(imgBlock);
}
// Make block bitmaps equally sized
FOREACH(blocklist_t, itr, m_vBlocks)
{
if(itr->bmpTrimmed.IsOk() && itr->bmpTrimmed.GetSize() != szLargestBitmap)
{
wxImage imgBlock = itr->bmpTrimmed.ConvertToImage();
_expandImage(imgBlock, szLargestBitmap);
itr->bmpTrimmed = wxBitmap(imgBlock);
}
}
// Add blocks to gallery
_repopulate();
}
void RibbonBlockGallery::_repopulate()
{
Clear();
FOREACH(blocklist_t, itr, m_vBlocks)
{
if(itr->pCategory->bEnabled && itr->bmpTrimmed.IsOk())
{
Append(itr->bmpTrimmed, itr->iBlock, (void*)&*itr);
}
}
Realise();
}
void RibbonBlockGallery::OnToggleCategory(wxCommandEvent& evt)
{
FOREACH(categorylist_t, itr, m_vCategories)
{
if((**itr).iID == evt.GetId())
{
(**itr).bEnabled = !(**itr).bEnabled;
_repopulate();
break;
}
}
}
bool RibbonBlockGallery::SelectAndMakeVisible(int iBlock)
{
unsigned int iCount = GetCount();
for(unsigned int i = 0; i < iCount; ++i)
{
wxRibbonGalleryItem *pItem = GetItem(i);
block_t *pBlock = reinterpret_cast<block_t*>(GetItemClientData(pItem));
if(pBlock->iBlock == iBlock)
{
SetSelection(pItem);
EnsureVisible(pItem);
return true;
}
}
FOREACH(blocklist_t, itr, m_vBlocks)
{
if(itr->iBlock == iBlock && !itr->pCategory->bEnabled)
{
itr->pCategory->bEnabled = true;
_repopulate();
return SelectAndMakeVisible(iBlock);
}
}
return false;
}
int RibbonBlockGallery::GetBlock(wxRibbonGalleryItem* pItem, int* pBaseBlock)
{
block_t *pBlock = reinterpret_cast<block_t*>(GetItemClientData(pItem));
if(pBaseBlock)
*pBaseBlock = pBlock->iBaseBlock;
return pBlock->iBlock;
}
void RibbonBlockGallery::_trimImage(wxImage& image)
{
int iOpaqueTop = 0;
int iOpaqueBottom = image.GetHeight() - 1;
int iOpaqueLeft = 0;
int iOpaqueRight = image.GetWidth() - 1;
for(; iOpaqueTop <= iOpaqueBottom; ++iOpaqueTop)
{
for(int iX = iOpaqueLeft; iX <= iOpaqueRight; ++iX)
{
if(!image.IsTransparent(iX, iOpaqueTop))
goto break1;
}
}
break1:;
for(; iOpaqueBottom >= iOpaqueTop; --iOpaqueBottom)
{
for(int iX = iOpaqueLeft; iX <= iOpaqueRight; ++iX)
{
if(!image.IsTransparent(iX, iOpaqueBottom))
goto break2;
}
}
break2:;
for(; iOpaqueLeft <= iOpaqueRight; ++iOpaqueLeft)
{
for(int iY = iOpaqueTop; iY <= iOpaqueBottom; ++iY)
{
if(!image.IsTransparent(iOpaqueLeft, iY))
goto break3;
}
}
break3:;
for(; iOpaqueRight >= iOpaqueLeft; --iOpaqueRight)
{
for(int iY = iOpaqueTop; iY <= iOpaqueBottom; ++iY)
{
if(!image.IsTransparent(iOpaqueRight, iY))
goto break4;
}
}
break4:;
image = image.Size(wxSize(iOpaqueRight - iOpaqueLeft + 1, iOpaqueBottom - iOpaqueTop + 1),
wxPoint(-iOpaqueLeft, -iOpaqueTop));
}
void RibbonBlockGallery::_expandImage(wxImage& image, wxSize size)
{
image = image.Size(size, wxPoint(
(size.GetWidth() - image.GetWidth()) / 2,
size.GetHeight() - image.GetHeight()
));
}
void RibbonBlockGallery::OnExtButton(wxCommandEvent& evt)
{
wxMenu mnCategories;
FOREACH(categorylist_t, itr, m_vCategories)
{
mnCategories.AppendCheckItem((**itr).iID, (**itr).sName)
->Check((**itr).bEnabled);
}
PopupMenu(&mnCategories);
}

View File

@@ -1,86 +0,0 @@
/*
Copyright (c) 2009 Peter "Corsix" Cawley
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once
// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
// for all others, include the necessary headers (this file is usually all you
// need because it includes almost all "standard" wxWidgets headers)
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
// ----------------------------
#include <wx/ribbon/gallery.h>
#include <vector>
#include "game.h"
class RibbonBlockGallery : public wxRibbonGallery
{
public:
RibbonBlockGallery(wxWindow* parent, wxWindowID id = wxID_ANY);
~RibbonBlockGallery();
void Populate(THSpriteSheet *pBlocks, const char* sCategory,
const char* sSubCategory, lua_State* L, int iInfoIndex);
bool SelectAndMakeVisible(int iBlock);
int GetBlock(wxRibbonGalleryItem* pItem, int* pBaseBlock);
void OnExtButton(wxCommandEvent& evt);
void OnToggleCategory(wxCommandEvent& evt);
protected:
struct category_t
{
wxString sName;
bool bEnabled;
int iID;
};
struct block_t
{
wxBitmap bmpTrimmed;
category_t* pCategory;
int iBlock;
int iBaseBlock;
};
// wxWidgets encourages use of wxArray over std::vector, but this isn't in
// wxWidgets core (and never will be), so it doesn't matter ^_^
typedef std::vector<block_t> blocklist_t;
typedef std::vector<category_t*> categorylist_t;
blocklist_t m_vBlocks;
categorylist_t m_vCategories;
void _trimImage(wxImage& image);
void _expandImage(wxImage& image, wxSize size);
void _clearCategories();
void _repopulate();
DECLARE_EVENT_TABLE();
};

View File

@@ -1,448 +0,0 @@
/*
Copyright (c) 2009 Peter "Corsix" Cawley
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "frmMain.h"
#include "../../CorsixTH/Src/main.h"
BEGIN_EVENT_TABLE(EmbeddedGamePanel, wxGLCanvas)
EVT_MOTION(EmbeddedGamePanel::_onMouseMove)
EVT_PAINT(EmbeddedGamePanel::_onPaint)
EVT_LEFT_UP(EmbeddedGamePanel::_onLeftUp)
EVT_LEFT_DOWN(EmbeddedGamePanel::_onLeftDown)
EVT_MIDDLE_UP(EmbeddedGamePanel::_onMiddleUp)
EVT_MIDDLE_DOWN(EmbeddedGamePanel::_onMiddleDown)
EVT_RIGHT_UP(EmbeddedGamePanel::_onRightUp)
EVT_RIGHT_DOWN(EmbeddedGamePanel::_onRightDown)
EVT_LEFT_DCLICK(EmbeddedGamePanel::_onLeftDoubleClick)
END_EVENT_TABLE()
IEmbeddedGamePanel::~IEmbeddedGamePanel()
{
}
EmbeddedGamePanel::EmbeddedGamePanel(wxWindow *pParent)
: wxGLCanvas(pParent, wxID_ANY, NULL, wxDefaultPosition,
wxDefaultSize, 0, wxGLCanvasName, wxNullPalette)
, m_pGLCanvas(NULL)
, m_pGLContext(NULL)
, m_pPrintTarget(NULL)
, m_L(NULL)
, m_Lthread(NULL)
, m_fnExtraLuaInit(NULL)
, m_pExtraLuaInitArg(NULL)
{
m_pGLCanvas = this;
m_pGLContext = new wxGLContext(m_pGLCanvas);
}
EmbeddedGamePanel::~EmbeddedGamePanel()
{
if(m_L)
lua_close(m_L);
delete m_pGLContext;
}
void EmbeddedGamePanel::setExtraLuaInitFunction(lua_CFunction fn, void* arg)
{
m_fnExtraLuaInit = fn;
m_pExtraLuaInitArg = arg;
}
void EmbeddedGamePanel::setLogWindow(frmLog *pLogWindow)
{
m_pPrintTarget = pLogWindow->getTextControl();
}
THMap* EmbeddedGamePanel::getMap()
{
THMap *pMap = NULL;
int iTop = lua_gettop(m_L);
lua_checkstack(m_L, 5);
lua_getglobal(m_L, "TheApp");
if(!lua_isnil(m_L, -1))
{
lua_getfield(m_L, -1, "map");
if(!lua_isnil(m_L, -1))
{
lua_getfield(m_L, -1, "th");
pMap = reinterpret_cast<THMap*>(lua_touserdata(m_L, -1));
}
}
lua_settop(m_L, iTop);
return pMap;
}
bool EmbeddedGamePanel::loadLua()
{
// Create state
m_L = luaL_newstate();
lua_atpanic(m_L, _l_panic);
// Save a pointer to ourselves in the registry
lua_pushliteral(m_L, "wxWindow");
lua_pushlightuserdata(m_L, reinterpret_cast<wxWindow*>(this));
lua_settable(m_L, LUA_REGISTRYINDEX);
// Open default libraries, and override appropriate bits
luaL_openlibs(m_L);
luaT_execute(m_L, "print = ...", _l_print);
// Set _MAP_EDITOR to true, to allow scripts to notice that they are
// running inside this component, rather than standalone.
luaT_execute(m_L, "_MAP_EDITOR = true");
// Load CorsixTH.lua and perform other initialisation needed by it
lua_settop(m_L, 0);
lua_pushcfunction(m_L, CorsixTH_lua_stacktrace);
lua_pushcfunction(m_L, CorsixTH_lua_main_no_eval);
lua_checkstack(m_L, wxTheApp->argc);
for(int i = 0; i < wxTheApp->argc; ++ i)
lua_pushstring(m_L, wxTheApp->argv[i]);
if(lua_pcall(m_L, wxTheApp->argc, 1, 1))
{
if(m_pPrintTarget)
{
m_pPrintTarget->AppendText(L"Error initialising Lua: ");
m_pPrintTarget->AppendText(lua_tostring(m_L, -1));
m_pPrintTarget->AppendText(L"\n");
}
return false;
}
// NB: CorsixTH_lua_main_no_eval will have loaded CorsixTH.lua and left it
// as the top value on the stack, but will not have executed it.
// The stack will hence have two things on it: the stacktrace function,
// and the loaded CorsixTH.lua
// Overwrite what CorsixTH_lua_main_no_eval registered for require("sdl")
// with our own function that uses wxWidgets to do what SDL would have.
luaT_execute(m_L, "package.preload.sdl = ...", _l_open_sdl);
// Replace the Surface:endFrame() function with our own
lua_getglobal(m_L, "require");
lua_pushliteral(m_L, "TH");
lua_call(m_L, 1, 1);
lua_getfield(m_L, -1, "surface");
lua_getfield(m_L, -1, "endFrame");
lua_pushcclosure(m_L, _l_end_frame, 1);
lua_setfield(m_L, -2, "endFrame");
lua_pop(m_L, 2);
// Perform extra initialisation
if(m_fnExtraLuaInit)
{
if(lua_cpcall(m_L, m_fnExtraLuaInit, m_pExtraLuaInitArg) != 0)
lua_pop(m_L, 1);
}
// Execute CorsixTH.lua in a coroutine
lua_getglobal(m_L, "coroutine");
lua_getfield(m_L, -1, "create");
lua_replace(m_L, -2);
lua_insert(m_L, -2);
lua_call(m_L, 1, 1);
lua_State *L = lua_tothread(m_L, -1);
if(lua_resume(L, 0) != LUA_YIELD)
{
if(m_pPrintTarget)
{
// Push debug.traceback onto m_L
lua_getglobal(m_L, "debug");
lua_getfield(m_L, -1, "traceback");
lua_replace(m_L, -2);
// Push the thread onto m_L
lua_pushvalue(m_L, -2);
// Push tostring(errmsg) onto m_L
lua_getglobal(m_L, "tostring");
lua_xmove(L, m_L, 1);
lua_call(m_L, 1, 1);
// Push constant 1 onto m_L
lua_pushinteger(m_L, 1);
// Call debug.traceback(thread, tostring(err), 1)
lua_call(m_L, 3, 1);
// Display resulting string and pop it
m_pPrintTarget->AppendText(L"Error initialising Lua: ");
m_pPrintTarget->AppendText(lua_tostring(m_L, -1));
m_pPrintTarget->AppendText(L"\n");
lua_pop(m_L, 1);
}
return false;
}
lua_settop(L, 1);
m_Lthread = L;
// The stack of the Lua states is now as follows:
// m_L: stacktrace function, m_Lthread <top
// m_Lthread: event dispatch coroutine <top
return true;
}
bool EmbeddedGamePanel::_resume(lua_State *L, int iNArgs, int iNRes)
{
// L will be an event handling coroutine.
// Start by sending the event to the coroutine by resuming it with the
// event arguments.
bool bGood = true;
if(lua_resume(L, iNArgs) != LUA_YIELD)
{
// Error occurred during event processing.
bGood = false;
// Transfer the error details to m_Lthread
int iNTransfer = lua_gettop(L);
if(lua_status(L) >= LUA_ERRRUN)
iNTransfer = 1;
lua_checkstack(m_Lthread, iNTransfer);
lua_xmove(L, m_Lthread, iNTransfer);
lua_settop(L, 0);
// Allow m_Lthread to respond to the error in an appropriate way
lua_resume(m_Lthread, iNTransfer);
}
else
{
// Event processed without errors, and will have returned true if
// a redraw needs to occur.
if(lua_toboolean(L, -1) != 0)
{
Refresh(false);
}
}
// Leave L with the desired number of return values.
lua_settop(L, iNRes);
return bGood;
}
void EmbeddedGamePanel::_onMouseMove(wxMouseEvent& evt)
{
// Keep track of relative mouse movements as well as absolute
wxPoint ptNew = evt.GetPosition();
wxPoint ptDelta = ptNew - m_ptMouse;
m_ptMouse = ptNew;
_dispatchEvent("motion", ptNew.x, ptNew.y, ptDelta.x, ptDelta.y);
}
void EmbeddedGamePanel::_onLeftUp(wxMouseEvent& evt)
{
_dispatchEvent("buttonup", SDL_BUTTON_LEFT, evt.GetX(), evt.GetY());
}
void EmbeddedGamePanel::_onLeftDown(wxMouseEvent& evt)
{
_dispatchEvent("buttondown", SDL_BUTTON_LEFT, evt.GetX(), evt.GetY());
}
void EmbeddedGamePanel::_onLeftDoubleClick(wxMouseEvent& evt)
{
_dispatchEvent("buttondown", "left_double", evt.GetX(), evt.GetY());
}
void EmbeddedGamePanel::_onRightUp(wxMouseEvent& evt)
{
_dispatchEvent("buttonup", SDL_BUTTON_RIGHT, evt.GetX(), evt.GetY());
}
void EmbeddedGamePanel::_onRightDown(wxMouseEvent& evt)
{
_dispatchEvent("buttondown", SDL_BUTTON_RIGHT, evt.GetX(), evt.GetY());
}
void EmbeddedGamePanel::_onMiddleUp(wxMouseEvent& evt)
{
_dispatchEvent("buttonup", SDL_BUTTON_MIDDLE, evt.GetX(), evt.GetY());
}
void EmbeddedGamePanel::_onMiddleDown(wxMouseEvent& evt)
{
_dispatchEvent("buttondown", SDL_BUTTON_MIDDLE, evt.GetX(), evt.GetY());
}
void EmbeddedGamePanel::_onPaint(wxPaintEvent& evt)
{
wxPaintDC dc(this);
m_pGLContext->SetCurrent(*m_pGLCanvas);
if(m_L == NULL)
{
// Its rather hacky to be loading the Lua side of things from within
// the paint handler, but Lua needs an OpenGL context to be active, and
// we cannot give it one during the EmbeddedGamePanel constructor.
loadLua();
}
// Update the OpenGL projection matrix and Lua window size settings to keep
// a 1:1 mapping between world space and screen space
const wxSize szClient = GetClientSize();
glViewport(0, 0, szClient.x, szClient.y);
GLdouble fWidth = (GLdouble)szClient.x;
GLdouble fHeight = (GLdouble)szClient.y;
THRenderTarget::setGLProjection(fWidth, fHeight);
if(m_L)
{
lua_getglobal(m_L, "TheApp");
if(lua_isnil(m_L, -1))
lua_pop(m_L, 1);
else
{
lua_getfield(m_L, -1, "config");
lua_pushinteger(m_L, szClient.x);
lua_setfield(m_L, -2, "width");
lua_pushinteger(m_L, szClient.y);
lua_setfield(m_L, -2, "height");
lua_pop(m_L, 2);
}
}
// Do the actual painting
if(m_Lthread)
{
lua_State *L = lua_tothread(m_Lthread, 1);
if(L == NULL)
{
for(int i = 1; i <= lua_gettop(m_L); ++i)
{
wxPrintf("m_L stack %i: %s\n", i, lua_typename(m_L, lua_type(m_L, i)));
}
for(int i = 1; i <= lua_gettop(m_Lthread); ++i)
{
wxPrintf("m_Lthread stack %i: %s\n", i, lua_typename(m_Lthread, lua_type(m_Lthread, i)));
}
}
lua_pushliteral(L, "frame");
_resume(L, 1, 0);
}
}
EmbeddedGamePanel* EmbeddedGamePanel::_getThis(lua_State *L)
{
lua_pushliteral(L, "wxWindow");
lua_gettable(L, LUA_REGISTRYINDEX);
EmbeddedGamePanel *pThis = reinterpret_cast<EmbeddedGamePanel*>(
reinterpret_cast<wxWindow*>(lua_touserdata(L, -1)));
lua_pop(L, 1);
return pThis;
}
int EmbeddedGamePanel::_l_print(lua_State *L)
{
EmbeddedGamePanel *pThis = _getThis(L);
if(pThis->m_pPrintTarget)
{
int iCount = lua_gettop(L);
lua_getglobal(L, "tostring");
for(int iArg = 1; iArg <= iCount; ++iArg)
{
lua_pushvalue(L, -1);
lua_pushvalue(L, iArg);
lua_call(L, 1, 1);
pThis->m_pPrintTarget->AppendText(lua_tostring(L, -1));
lua_pop(L, 1);
if(iArg != iCount)
pThis->m_pPrintTarget->AppendText(L"\t");
}
pThis->m_pPrintTarget->AppendText(L"\n");
}
return 0;
}
int EmbeddedGamePanel::_l_panic(lua_State *L)
{
const char *sMessage = lua_tostring(L, -1);
::wxMessageBox(wxString(L"Lua Panic!\n") + wxString(sMessage ? sMessage : ""),
wxString(L"Lua Panic"), wxOK | wxICON_ERROR | wxCENTRE);
return 0;
}
int EmbeddedGamePanel::_l_end_frame(lua_State *L)
{
// Call the original Surface:endFrame() function
lua_pushvalue(L, lua_upvalueindex(1));
lua_insert(L, 1);
lua_call(L, lua_gettop(L) - 1, LUA_MULTRET);
// Update the display
EmbeddedGamePanel *pThis = _getThis(L);
pThis->m_pGLCanvas->SwapBuffers();
// Return whatever the original returned
return lua_gettop(L);
}
static int l_init(lua_State *L)
{
lua_pushboolean(L, 1);
return 1;
}
static int l_get_fps(lua_State *L)
{
lua_pushnumber(L, 1);
return 1;
}
static int l_nop(lua_State *L)
{
return 0;
}
static int l_get_ticks(lua_State *L)
{
// Not the same as the game's sdl.getTicks(), but it is sufficient for the
// purpose (initialising the random number generator).
lua_pushnumber(L, ::wxGetLocalTime());
return 1;
}
static const struct luaL_reg sdllib[] = {
{"init", l_init},
//{"mainloop", coroutine.yield},
{"getFPS", l_get_fps},
{"trackFPS", l_nop},
{"limitFPS", l_nop},
{"modifyKeyboardRepeat", l_nop},
{"getTicks", l_get_ticks},
{NULL, NULL}
};
static const struct luaL_reg sdl_wmlib[] = {
{"setIconWin32", l_nop},
{"setCaption", l_nop},
{"showCursor", l_nop},
{NULL, NULL}
};
int EmbeddedGamePanel::_l_open_sdl(lua_State *L)
{
luaL_register(L, "sdl", sdllib);
lua_getglobal(L, "coroutine");
lua_getfield(L, -1, "yield");
lua_setfield(L, -3, "mainloop");
lua_pop(L, 1);
lua_newtable(L);
lua_pushvalue(L, -1);
lua_setfield(L, -3, "wm");
luaL_register(L, NULL, sdl_wmlib);
lua_pop(L, 1);
lua_newtable(L);
lua_pushboolean(L, 0);
lua_setfield(L, -2, "loaded");
lua_setfield(L, -2, "audio");
return 1;
}

View File

@@ -1,146 +0,0 @@
/*
Copyright (c) 2009 Peter "Corsix" Cawley
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once
// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
// for all others, include the necessary headers (this file is usually all you
// need because it includes almost all "standard" wxWidgets headers)
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
// ----------------------------
#include <wx/glcanvas.h>
#include "game.h"
#include "frmLog.h"
class IEmbeddedGamePanel
{
public:
virtual ~IEmbeddedGamePanel();
virtual void setExtraLuaInitFunction(lua_CFunction fn, void* arg) = 0;
virtual void setLogWindow(frmLog *pLogWindow) = 0;
virtual bool loadLua() = 0;
virtual lua_State* getLua() = 0;
virtual THMap* getMap() = 0;
};
//! GUI component which acts as an instance of CorsixTH
/*!
The component contains a Lua instance which executes the normal CorsixTH
Lua scripts. Mouse and keyboard events to the component are forwarded to
said Lua instance in the same way as they are for a standalone CorsixTH
instance, and the visual representation of the component is what would
normally get displayed in a standalone CorsixTH window.
Lua scripts can tell if they are being executed from within this, as the
global variable _MAP_EDITOR will be set to true.
*/
class EmbeddedGamePanel : public wxGLCanvas, public IEmbeddedGamePanel
{
public:
EmbeddedGamePanel(wxWindow *pParent);
~EmbeddedGamePanel();
void setExtraLuaInitFunction(lua_CFunction fn, void* arg);
void setLogWindow(frmLog *pLogWindow);
bool loadLua();
lua_State* getLua() {return m_L;}
THMap* getMap();
protected:
// OpenGL rendering stuff
wxGLCanvas* m_pGLCanvas;
wxGLContext* m_pGLContext;
//! A text control which is used for the output of print() calls
wxTextCtrl* m_pPrintTarget;
//! The top-level Lua instance
lua_State* m_L;
//! A substate of m_L which is used for executing the CorsixTH instance,
// as this allows the execution to yield and resume "asynchronously".
lua_State* m_Lthread;
//! A user-supplied function to be called during Lua initialisation.
lua_CFunction m_fnExtraLuaInit;
//! An argument to m_fnExtraLuaInit, delivered as a light userdata.
void* m_pExtraLuaInitArg;
//! The last recorded position of the mouse cursor - used to calculate
// the difference in position each time the mouse is moved.
wxPoint m_ptMouse;
static int _l_print(lua_State *L);
static int _l_panic(lua_State *L);
static int _l_open_sdl(lua_State *L);
static int _l_end_frame(lua_State *L);
static EmbeddedGamePanel* _getThis(lua_State *L);
void _onPaint(wxPaintEvent& evt);
void _onMouseMove(wxMouseEvent& evt);
void _onLeftUp(wxMouseEvent& evt);
void _onLeftDown(wxMouseEvent& evt);
void _onLeftDoubleClick(wxMouseEvent& evt);
void _onRightUp(wxMouseEvent& evt);
void _onRightDown(wxMouseEvent& evt);
void _onMiddleUp(wxMouseEvent& evt);
void _onMiddleDown(wxMouseEvent& evt);
template <typename T1, typename T2, typename T3>
void _dispatchEvent(const char* sName, T1 a1, T2 a2, T3 a3)
{
if(m_Lthread)
{
lua_State *L = lua_tothread(m_Lthread, 1);
lua_pushstring(L, sName);
luaT_push(L, a1);
luaT_push(L, a2);
luaT_push(L, a3);
_resume(L, 4, 0);
}
}
template <typename T1, typename T2, typename T3, typename T4>
void _dispatchEvent(const char* sName, T1 a1, T2 a2, T3 a3, T4 a4)
{
if(m_Lthread)
{
lua_State *L = lua_tothread(m_Lthread, 1);
lua_pushstring(L, sName);
luaT_push(L, a1);
luaT_push(L, a2);
luaT_push(L, a3);
luaT_push(L, a4);
_resume(L, 5, 0);
}
}
bool _resume(lua_State *L, int iNArgs, int iNRes);
DECLARE_EVENT_TABLE();
};

View File

@@ -1,43 +0,0 @@
/*
Copyright (c) 2009 Peter "Corsix" Cawley
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "frmLog.h"
BEGIN_EVENT_TABLE(frmLog, wxFrame)
END_EVENT_TABLE()
frmLog::frmLog()
: wxFrame(NULL, wxID_ANY, L"CorsixTH Lua Log Window", wxDefaultPosition,
wxSize(400, 480), wxCAPTION | wxRESIZE_BORDER)
{
m_pTextCtrl = new wxTextCtrl(this, wxID_ANY, L"", wxDefaultPosition,
wxDefaultSize, wxTE_READONLY | wxTE_MULTILINE);
wxSizer *pTopSizer = new wxBoxSizer(wxVERTICAL);
pTopSizer->Add(m_pTextCtrl, 1, wxEXPAND);
SetSizer(pTopSizer);
Show();
}
frmLog::~frmLog()
{
}

View File

@@ -1,50 +0,0 @@
/*
Copyright (c) 2009 Peter "Corsix" Cawley
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once
// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
// for all others, include the necessary headers (this file is usually all you
// need because it includes almost all "standard" wxWidgets headers)
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
// ----------------------------
class frmLog : public wxFrame
{
public:
frmLog();
~frmLog();
wxTextCtrl* getTextControl() {return m_pTextCtrl;}
protected:
wxTextCtrl* m_pTextCtrl;
DECLARE_EVENT_TABLE();
};

View File

@@ -1,761 +0,0 @@
/*
Copyright (c) 2009 Peter "Corsix" Cawley
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "frmMain.h"
#include "th_map_wrapper.h"
#include <wx/file.h>
#include <wx/filename.h>
BEGIN_EVENT_TABLE(frmMain, wxFrame)
EVT_RIBBONBAR_PAGE_CHANGED(wxID_ANY, frmMain::_onRibbonPageChanged)
EVT_RIBBONGALLERY_SELECTED(ID_GALLERY_FLOOR1, frmMain::_onFloorGallery1Select)
EVT_RIBBONGALLERY_SELECTED(ID_GALLERY_FLOOR2, frmMain::_onFloorGallery2Select)
EVT_RIBBONGALLERY_SELECTED(ID_GALLERY_WALL1, frmMain::_onWallGallery1Select)
EVT_RIBBONGALLERY_SELECTED(ID_GALLERY_WALL2, frmMain::_onWallGallery2Select)
EVT_RIBBONGALLERY_SELECTED(ID_GALLERY_PARCELS, frmMain::_onParcelGallerySelect)
EVT_RIBBONBUTTONBAR_CLICKED(wxID_NEW, frmMain::_onNew)
EVT_RIBBONBUTTONBAR_CLICKED(wxID_OPEN, frmMain::_onOpen)
EVT_RIBBONBUTTONBAR_CLICKED(wxID_SAVE, frmMain::_onSave)
EVT_RIBBONBUTTONBAR_CLICKED(wxID_UNDO, frmMain::_onUndo)
EVT_RIBBONBUTTONBAR_CLICKED(wxID_REDO, frmMain::_onRedo)
EVT_RIBBONBUTTONBAR_DROPDOWN_CLICKED(wxID_SAVE, frmMain::_onSaveMenu)
EVT_MENU(ID_SAVE_IN_DROPDOWN, frmMain::_onSaveMenuSave)
EVT_MENU(ID_SAVEAS, frmMain::_onSaveMenuSaveAs)
EVT_RIBBONBUTTONBAR_CLICKED(ID_VIEW_WALLS, frmMain::_onViewWalls)
EVT_RIBBONBUTTONBAR_CLICKED(ID_VIEW_FLAGS, frmMain::_onViewFlags)
EVT_RIBBONBUTTONBAR_CLICKED(ID_VIEW_PARCELS, frmMain::_onViewParcels)
EVT_RIBBONBUTTONBAR_CLICKED(ID_VIEW_POSITIONS, frmMain::_onViewPositions)
EVT_SIZE(frmMain::_onResize)
END_EVENT_TABLE()
frmMain::frmMain()
: wxFrame(NULL, wxID_ANY, L"CorsixTH Map Editor",
wxDefaultPosition, wxSize(800, 600))
{
m_sFrameCaption = wxFrame::GetTitle();
_setFilename(wxEmptyString);
wxSizer *pMainSizer = new wxBoxSizer(wxVERTICAL);
wxSplitterWindow* pSplitter = new wxSplitterWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_3D);
pSplitter->SetMinimumPaneSize(250);
wxPanel *pLeftPanel = new wxPanel(pSplitter, wxID_ANY, wxDefaultPosition, wxDefaultSize);
wxPanel *pRightPanel = new wxPanel(pSplitter, wxID_ANY, wxDefaultPosition, wxDefaultSize);
wxSizer *pLeftSizer = new wxBoxSizer(wxVERTICAL);
wxSizer *pRightSizer = new wxBoxSizer(wxVERTICAL);
m_pRibbon = new wxRibbonBar(pLeftPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxRIBBON_BAR_FLOW_VERTICAL | wxRIBBON_BAR_SHOW_PAGE_LABELS);
m_pRibbon->SetArtProvider(new wxRibbonMSWArtProvider);
m_pRibbon->SetTabCtrlMargins(0, 0);
m_pHomePage = new wxRibbonPage(m_pRibbon, wxID_ANY, L"Home");
wxRibbonPage* pFloorPage = new wxRibbonPage(m_pRibbon, wxID_ANY, L"Floors");
wxRibbonPanel* pFloorSimplePanel = new wxRibbonPanel(pFloorPage, wxID_ANY, L"Simple Tiles");
m_pFloorGallery1 = new RibbonBlockGallery(pFloorSimplePanel, ID_GALLERY_FLOOR1);
wxRibbonPanel* pFloorDecoratedPanel = new wxRibbonPanel(pFloorPage, wxID_ANY, L"Decorated Tiles");
m_pFloorGallery2 = new RibbonBlockGallery(pFloorDecoratedPanel, ID_GALLERY_FLOOR2);
wxRibbonPage* pWallPage = new wxRibbonPage(m_pRibbon, wxID_ANY, L"Walls");
wxRibbonPanel* pWallWestPanel = new wxRibbonPanel(pWallPage, wxID_ANY, L"West");
m_pWallGallery1 = new RibbonBlockGallery(pWallWestPanel, ID_GALLERY_WALL1);
wxRibbonPanel* pWallNorthPanel = new wxRibbonPanel(pWallPage, wxID_ANY, L"North");
m_pWallGallery2 = new RibbonBlockGallery(pWallNorthPanel, ID_GALLERY_WALL2);
m_pRibbon->Realize();
m_pGamePanel = new ScrollableGamePanel(pRightPanel);
m_pGamePanel->setExtraLuaInitFunction(_l_init, this);
m_pGamePanel->setLogWindow(m_pLogWindow = new frmLog);
wxPoint ptLogWindow = GetPosition();
ptLogWindow.x += GetSize().GetWidth();
m_pLogWindow->SetPosition(ptLogWindow);
pLeftSizer->Add(m_pRibbon, 1, wxALL | wxEXPAND);
pRightSizer->Add(m_pGamePanel, 1, wxALL | wxEXPAND);
pLeftPanel->SetSizer(pLeftSizer);
pRightPanel->SetSizer(pRightSizer);
pSplitter->SplitVertically(pLeftPanel,pRightPanel);
pSplitter->SetSashPosition(250);
pMainSizer->Add(pSplitter, 1, wxEXPAND);
SetSizer(pMainSizer);
}
void frmMain::_setFilename(const wxString& sFilename)
{
m_sFilename = sFilename;
wxString sShortName("Untitled");
wxFileName oFilename(sFilename);
if(!oFilename.GetFullName().empty())
sShortName = oFilename.GetFullName();
SetTitle(m_sFrameCaption + wxT(" - ") + sShortName);
}
frmMain::~frmMain()
{
m_pLogWindow->Close();
}
void frmMain::_onRibbonPageChanged(wxRibbonBarEvent& evt)
{
switch(m_pRibbon->GetActivePage())
{
case 0:
if(m_bViewParcels)
_setLuaParcelBrush(m_iParcelBrush);
break;
case 1:
_setLuaBlockBrushFloorTab();
break;
case 2:
_setLuaBlockBrushWallsTab();
break;
}
}
struct do_load_level_t
{
const char* sData;
size_t iLength;
frmMain* pThis;
};
void frmMain::_onNew(wxRibbonButtonBarEvent& evt)
{
do_load_level_t oParams = {NULL, 0, this};
lua_State* L = m_pGamePanel->getLua();
if(lua_cpcall(L, _l_do_load, reinterpret_cast<void*>(&oParams)) != 0)
lua_pop(L, 1);
_setFilename(wxEmptyString);
m_pGamePanel->Refresh();
}
wxString frmMain::_getMapsDirectory()
{
return wxEmptyString;
}
wxString frmMain::_getMapsFilter()
{
wxString sFilter = wxT("Theme Hospital maps (*.L[0-9]+)|");
// *.L[0-9]* isn't quite the right filter, but it is as close as reasonably
// possible to *.L[0-9]+ which file filters can reasonably get
wxString sTHMapEndings = wxT("");
char cSep = ';';
for(int i = 0; i < 10; ++i)
{
if(i == 9) cSep = '|';
sTHMapEndings += wxString::Format(L"*.L%i*%c", i, cSep);
}
sFilter += sTHMapEndings;
sFilter += wxT("CorsixTH maps (*.map)|*.map|");
sFilter += wxT("All maps (*.map, *.L[0-9]+)|*.map;");
sFilter += sTHMapEndings;
sFilter += wxT("All files (*.*)|*.*");
return sFilter;
}
void frmMain::_onOpen(wxRibbonButtonBarEvent& evt)
{
wxString sDirectory = _getMapsDirectory();
wxString sFilter = _getMapsFilter();
wxFileDialog oOpenDialog(this, wxFileSelectorPromptStr, sDirectory,
wxEmptyString, sFilter, wxFD_OPEN | wxFD_FILE_MUST_EXIST);
oOpenDialog.SetFilterIndex(2);
if(oOpenDialog.ShowModal() != wxID_OK)
return;
wxFile fFile;
if(!fFile.Open(oOpenDialog.GetPath()))
return;
size_t iLength = static_cast<size_t>(fFile.Length());
char* sData = new (std::nothrow) char[iLength];
if(!sData)
return;
if(fFile.Read(sData, iLength) != iLength)
{
delete[] sData;
return;
}
do_load_level_t oParams = {sData, iLength, this};
lua_State* L = m_pGamePanel->getLua();
if(lua_cpcall(L, _l_do_load, reinterpret_cast<void*>(&oParams)) != 0)
lua_pop(L, 1);
delete[] sData;
_setFilename(oOpenDialog.GetPath());
m_pGamePanel->Refresh();
}
int frmMain::_l_do_load(lua_State *L)
{
lua_getglobal(L, "TheApp");
lua_getfield(L, -1, "loadLevel");
lua_insert(L, -2);
do_load_level_t *pParams = reinterpret_cast<do_load_level_t*>(lua_touserdata(L, 1));
size_t iLength = pParams->iLength;
const char* sData = pParams->sData;
lua_pushlstring(L, sData, iLength);
if(iLength >= 3 && sData[0] == 'R' && sData[1] == 'N' && sData[2] == 'C')
{
lua_getglobal(L, "require");
lua_pushliteral(L, "rnc");
lua_call(L, 1, 1);
lua_getfield(L, -1, "decompress");
lua_insert(L, -3);
lua_call(L, 2, 1);
}
lua_call(L, 2, 0);
pParams->pThis->_applyViewWalls();
pParams->pThis->_applyViewOverlay();
return 0;
}
void frmMain::_onSave(wxRibbonButtonBarEvent& evt)
{
wxCommandEvent dummy;
_onSaveMenuSave(dummy);
}
void frmMain::_onSaveMenu(wxRibbonButtonBarEvent& evt)
{
wxMenu mnuPopup;
mnuPopup.Append(ID_SAVE_IN_DROPDOWN, "Save");
mnuPopup.Append(ID_SAVEAS, "Save As");
evt.PopupMenu(&mnuPopup);
}
void frmMain::_onUndo(wxRibbonButtonBarEvent& evt)
{
_doLuaUndo();
}
void frmMain::_onRedo(wxRibbonButtonBarEvent& evt)
{
_doLuaRedo();
}
struct map_save_t
{
wxFile fFile;
static void writer(void* pThis_, const unsigned char* pData, size_t iLen)
{
map_save_t* pThis = reinterpret_cast<map_save_t*>(pThis_);
pThis->fFile.Write(reinterpret_cast<const void*>(pData), iLen);
}
};
void frmMain::_onSaveMenuSave(wxCommandEvent& evt)
{
if(m_sFilename.empty())
{
_onSaveMenuSaveAs(evt);
return;
}
map_save_t oSave;
if(oSave.fFile.Open(m_sFilename, wxFile::write))
{
lua_State* L = m_pGamePanel->getLua();
luaT_execute(L, "return TheApp.world.map.th");
THMap *pMap = reinterpret_cast<THMap*>(lua_touserdata(L, -1));
lua_pop(L, 1);
THMapWrapper::autoSetHelipad(pMap);
luaT_execute(L, "return TheApp.ui:ScreenToWorld(...)",
m_pGamePanel->GetSize().GetWidth() / 2,
m_pGamePanel->GetSize().GetHeight() / 2);
int iCameraX = (int)lua_tointeger(L, -2);
int iCameraY = (int)lua_tointeger(L, -1);
lua_pop(L, 2);
pMap->setPlayerCameraTile(0, iCameraX, iCameraY);
pMap->save(map_save_t::writer, reinterpret_cast<void*>(&oSave));
::wxMessageBox(wxT("Map saved."), wxT("Save"), wxOK | wxCENTER |
wxICON_INFORMATION, this);
}
}
void frmMain::_onSaveMenuSaveAs(wxCommandEvent& evt)
{
wxString sDirectory = _getMapsDirectory();
wxString sFilter = _getMapsFilter();
wxFileDialog oSaveDialog(this, wxFileSelectorPromptStr, sDirectory,
m_sFilename, sFilter, wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
oSaveDialog.SetFilterIndex(2);
if(oSaveDialog.ShowModal() != wxID_OK)
return;
_setFilename(oSaveDialog.GetPath());
_onSaveMenuSave(evt);
}
void frmMain::_onViewWalls(wxRibbonButtonBarEvent& evt)
{
m_bViewWalls = evt.IsChecked();
_applyViewWalls();
m_pGamePanel->Refresh();
}
void frmMain::_onViewFlags(wxRibbonButtonBarEvent& evt)
{
m_bViewFlags = evt.IsChecked();
_applyViewOverlay();
m_pGamePanel->Refresh();
}
void frmMain::_onViewParcels(wxRibbonButtonBarEvent& evt)
{
m_bViewParcels = evt.IsChecked();
_applyViewOverlay();
m_pGamePanel->Refresh();
if(evt.IsChecked())
{
wxRibbonPanel* pParcelPanel = new wxRibbonPanel(m_pHomePage,
ID_PARCEL_PANEL, L"Parcels");
wxRibbonGallery* pParcelGallery = new wxRibbonGallery(pParcelPanel,
ID_GALLERY_PARCELS);
_populateParcelGallery(pParcelGallery);
}
else
{
wxWindow* pParcelPanel = m_pHomePage->FindWindow(ID_PARCEL_PANEL);
if(pParcelPanel)
pParcelPanel->Destroy();
}
m_pRibbon->Realize();
}
void frmMain::_onViewPositions(wxRibbonButtonBarEvent& evt)
{
m_bViewPositions = evt.IsChecked();
_applyViewOverlay();
m_pGamePanel->Refresh();
}
wxBitmap frmMain::_asBitmap(THSpriteSheet* pSheet, unsigned int iSprite)
{
unsigned int iWidth, iHeight;
pSheet->getSpriteSize(iSprite, &iWidth, &iHeight);
wxImage imgSprite;
imgSprite.Create(iWidth, iHeight);
if(!imgSprite.HasAlpha())
imgSprite.InitAlpha();
pSheet->wxDrawSprite(iSprite, imgSprite.GetData(), imgSprite.GetAlpha());
return wxBitmap(imgSprite);
}
void frmMain::_populateParcelGallery(wxRibbonGallery* pGallery)
{
THSpriteSheet *pBlocksSheet;
THSpriteSheet *pOutlineSheet;
THSpriteSheet *pFontSheet;
{
lua_State *L = m_pGamePanel->getLua();
luaT_execute(L, "return TheApp.map.blocks");
pBlocksSheet = reinterpret_cast<THSpriteSheet*>(lua_touserdata(L, -1));
luaT_execute(L, "return TheApp.map.cell_outline");
pOutlineSheet = reinterpret_cast<THSpriteSheet*>(lua_touserdata(L, -1));
luaT_execute(L, "return TheApp.gfx:loadBuiltinFont()");
pFontSheet = reinterpret_cast<THBitmapFont*>(lua_touserdata(L, -1))
->getSpriteSheet();
lua_pop(L, 3);
}
wxBitmap bmOutline(_asBitmap(pBlocksSheet, 74));
wxMemoryDC dcMem;
dcMem.SelectObject(bmOutline);
for(int i = 0; i < 4; ++i)
{
dcMem.DrawBitmap(_asBitmap(pOutlineSheet, 18 + i), 0, 0);
}
dcMem.SelectObject(wxNullBitmap);
wxBitmap bmNumbers[10];
for(int i = 0; i < 10; ++i)
{
bmNumbers[i] = _asBitmap(pFontSheet, '0' + i - 31);
}
for(intptr_t iParcel = 0; iParcel < 32; ++iParcel)
{
wxBitmap bmParcel(bmOutline);
dcMem.SelectObject(bmParcel);
char sMsg[8];
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4996)
#endif
sprintf(sMsg, "%i", iParcel);
#ifdef _MSC_VER
#pragma warning(pop)
#endif
int iX = 0, iY = 0;
for(char* s = sMsg; *s; ++s)
{
wxBitmap& bm = bmNumbers[*s - '0'];
iX += bm.GetWidth();
iY = std::max(iY, bm.GetHeight());
}
iX = (bmParcel.GetWidth() - iX) / 2;
iY = (bmParcel.GetHeight() - iY) / 2;
for(char* s = sMsg; *s; ++s)
{
wxBitmap& bm = bmNumbers[*s - '0'];
dcMem.DrawBitmap(bm, iX, iY);
iX += bm.GetWidth();
}
dcMem.SelectObject(wxNullBitmap);
pGallery->SetItemClientData(pGallery->Append(bmParcel, iParcel),
reinterpret_cast<void*>(iParcel));
}
}
void frmMain::_onResize(wxSizeEvent& evt)
{
wxRect rcLogWindow = wxRect(GetPosition(), m_pLogWindow->GetSize());
rcLogWindow.x += evt.GetSize().GetWidth();
rcLogWindow.height = evt.GetSize().GetHeight();
m_pLogWindow->SetSize(rcLogWindow);
evt.Skip();
}
int frmMain::_l_init(lua_State *L)
{
frmMain *pThis = reinterpret_cast<frmMain*>(lua_touserdata(L, 1));
THMapWrapper::wrap(L);
// Create a new environment table: {
// [1] = <light userdata pThis>,
// }
lua_newtable(L);
lua_insert(L, 1);
lua_rawseti(L, 1, 1);
lua_replace(L, LUA_ENVIRONINDEX);
// NB: Following functions registered with above environment table
luaT_execute(L, "MapEditorSetBlocks = ...", _l_set_blocks);
luaT_execute(L, "MapEditorSetBlockBrush = ...", _l_set_block_brush);
luaT_execute(L, "MapEditorInitWithLuaApp = ...", _l_init_with_lua_app);
return 0;
}
class FullSizeButtonBar : public wxRibbonButtonBar
{
public:
FullSizeButtonBar(wxWindow* parent, wxWindowID id)
: wxRibbonButtonBar(parent, id)
{
}
virtual wxSize GetMinSize() const
{
return DoGetBestSize();
}
protected:
virtual wxSize DoGetNextSmallerSize(wxOrientation direction,
wxSize relative_to) const
{
return relative_to;
}
};
int frmMain::_l_init_with_lua_app(lua_State *L)
{
lua_rawgeti(L, LUA_ENVIRONINDEX, 1);
frmMain *pThis = reinterpret_cast<frmMain*>(lua_touserdata(L, -1));
lua_pop(L, 1);
lua_getfield(L, 1, "getBitmapDir");
lua_pushvalue(L, 1);
lua_call(L, 1, 1);
wxString sBitmapDir = lua_tostring(L, -1);
lua_pop(L, 1);
wxRibbonPage* pHomePage = pThis->m_pHomePage;
wxRibbonPanel* pFilePanel = new wxRibbonPanel(pHomePage, wxID_ANY, wxT("File"));
wxRibbonButtonBar* pFileButtons = new FullSizeButtonBar(pFilePanel, wxID_ANY);
#define BITMAP(name) wxBitmap(sBitmapDir + (wxT(name) wxT("32.png")), wxBITMAP_TYPE_PNG)
pFileButtons->AddButton(wxID_NEW, wxT("New"), BITMAP("new"));
pFileButtons->AddButton(wxID_OPEN, wxT("Load"), BITMAP("open"));
pFileButtons->AddHybridButton(wxID_SAVE, wxT("Save"), BITMAP("save"));
pFileButtons->AddButton(wxID_UNDO, wxT("Undo"), BITMAP("undo"));
pFileButtons->AddButton(wxID_REDO, wxT("Redo"), BITMAP("redo"));
wxRibbonPanel* pViewPanel = new wxRibbonPanel(pHomePage, wxID_ANY, wxT("View"));
wxRibbonButtonBar* pViewButtons = new FullSizeButtonBar(pViewPanel, wxID_ANY);
pViewButtons->AddToggleButton(ID_VIEW_WALLS, wxT("Walls"), BITMAP("transparent_walls"));
pViewButtons->ToggleButton(ID_VIEW_WALLS, pThis->m_bViewWalls = true);
pViewButtons->AddToggleButton(ID_VIEW_FLAGS, wxT("Flags"), BITMAP("flags"));
pViewButtons->ToggleButton(ID_VIEW_FLAGS, pThis->m_bViewFlags = false);
pViewButtons->AddToggleButton(ID_VIEW_PARCELS, wxT("Parcels"), BITMAP("parcels"));
pViewButtons->ToggleButton(ID_VIEW_PARCELS, pThis->m_bViewParcels = false);
pViewButtons->AddToggleButton(ID_VIEW_POSITIONS, wxT("Positions"), BITMAP("positions"));
pViewButtons->ToggleButton(ID_VIEW_POSITIONS, pThis->m_bViewPositions = false);
#undef BITMAP
pThis->m_pRibbon->Realise();
return 0;
}
void frmMain::_applyViewWalls()
{
m_pGamePanel->getMap()->setAllWallDrawFlags(m_bViewWalls ? 0 : THDF_Alpha50);
}
void frmMain::_applyViewOverlay()
{
if(m_bViewFlags || m_bViewParcels || m_bViewPositions)
{
lua_State *L = m_pGamePanel->getLua();
luaT_execute(L, "return TheApp.gfx:loadBuiltinFont(), TheApp.map.cell_outline");
THFont *pFont = reinterpret_cast<THFont*>(lua_touserdata(L, -2));
THSpriteSheet *pSprites = reinterpret_cast<THSpriteSheet*>(lua_touserdata(L, -1));
lua_pop(L, 2);
THMapTypicalOverlay *pFlags = NULL;
THMapTypicalOverlay *pParcels = NULL;
THMapPositionsOverlay *pPositions = NULL;
if(m_bViewFlags)
{
pFlags = new THMapFlagsOverlay;
pFlags->setFont(pFont, false);
pFlags->setSprites(pSprites, false);
}
if(m_bViewParcels)
{
pParcels = new THMapParcelsOverlay;
pParcels->setFont(pFont, false);
pParcels->setSprites(pSprites, false);
}
if(m_bViewPositions)
{
pPositions = new THMapPositionsOverlay;
pPositions->setFont(pFont, false);
pPositions->setSprites(pSprites, false);
pPositions->setBackgroundSprite(2);
}
THMapOverlayPair *pOverlays = new THMapOverlayPair;
pOverlays->setFirst(pParcels, true);
pOverlays->setSecond(pFlags, true);
THMapOverlayPair *pOverlays2 = new THMapOverlayPair;
pOverlays2->setFirst(pOverlays, true);
pOverlays2->setSecond(pPositions, true);
m_pGamePanel->getMap()->setOverlay(pOverlays2, true);
}
else
m_pGamePanel->getMap()->setOverlay(NULL, false);
}
int frmMain::_l_set_blocks(lua_State *L)
{
lua_rawgeti(L, LUA_ENVIRONINDEX, 1);
frmMain *pThis = reinterpret_cast<frmMain*>(lua_touserdata(L, -1));
lua_pop(L, 1);
luaL_checktype(L, 1, LUA_TUSERDATA);
luaL_checktype(L, 2, LUA_TTABLE);
pThis->m_iFloorTabBrushF = 0;
pThis->m_iFloorTabBrushW1 = 0;
pThis->m_iFloorTabBrushW2 = 0;
pThis->m_iWallsTabBrushF = 0;
pThis->m_iWallsTabBrushW1 = 0;
pThis->m_iWallsTabBrushW2 = 0;
THSpriteSheet *pSheet = reinterpret_cast<THSpriteSheet*>(lua_touserdata(L, 1));
pThis->m_pFloorGallery1->Populate(pSheet, "floor", "simple", L, 2);
pThis->m_pFloorGallery2->Populate(pSheet, "floor", "decorated", L, 2);
pThis->m_pWallGallery1->Populate(pSheet, "wall", "west", L, 2);
pThis->m_pWallGallery2->Populate(pSheet, "wall", "north", L, 2);
pThis->m_pRibbon->Realize();
pThis->Layout();
return 0;
}
int frmMain::_l_set_block_brush(lua_State *L)
{
lua_rawgeti(L, LUA_ENVIRONINDEX, 1);
frmMain *pThis = reinterpret_cast<frmMain*>(lua_touserdata(L, -1));
lua_pop(L, 1);
int iBlock;
if(pThis->m_pRibbon->GetActivePage() == 0)
pThis->m_pRibbon->SetActivePage(1);
wxRibbonGalleryEvent evt(wxEVT_COMMAND_RIBBONGALLERY_SELECTED);
if(pThis->m_pRibbon->GetActivePage() == 1)
{
// Floor
iBlock = luaL_checkint(L, 1);
if(pThis->m_pFloorGallery1->SelectAndMakeVisible(iBlock))
{
pThis->m_pFloorGallery2->SetSelection(NULL);
evt.SetGallery(pThis->m_pFloorGallery1);
}
else if(pThis->m_pFloorGallery2->SelectAndMakeVisible(iBlock))
{
pThis->m_pFloorGallery1->SetSelection(NULL);
evt.SetGallery(pThis->m_pFloorGallery2);
}
else
return 0;
}
else
{
// Wall
iBlock = luaL_checkint(L, 2);
if(pThis->m_pWallGallery1->SelectAndMakeVisible(iBlock))
{
pThis->m_pWallGallery2->SetSelection(NULL);
evt.SetGallery(pThis->m_pWallGallery1);
}
else if(pThis->m_pWallGallery2->SelectAndMakeVisible(iBlock))
{
pThis->m_pWallGallery1->SetSelection(NULL);
evt.SetGallery(pThis->m_pWallGallery2);
}
else
return 0;
}
evt.SetId(evt.GetGallery()->GetId());
evt.SetGalleryItem(evt.GetGallery()->GetSelection());
pThis->ProcessEvent(evt);
return 0;
}
void frmMain::_onFloorGallery1Select(wxRibbonGalleryEvent& evt)
{
if(evt.GetGalleryItem() != NULL)
{
m_pFloorGallery2->SetSelection(NULL);
int iBaseBlock;
int iBlock = m_pFloorGallery1->GetBlock(evt.GetGalleryItem(), &iBaseBlock);
if(iBaseBlock != 0)
_setLuaBlockBrushFloorTab(iBaseBlock, iBlock, 0);
else
_setLuaBlockBrushFloorTab(iBlock, 0, 0);
}
}
void frmMain::_onFloorGallery2Select(wxRibbonGalleryEvent& evt)
{
if(evt.GetGalleryItem() != NULL)
{
m_pFloorGallery1->SetSelection(NULL);
int iBaseBlock;
int iBlock = m_pFloorGallery2->GetBlock(evt.GetGalleryItem(), &iBaseBlock);
if(iBaseBlock != 0)
_setLuaBlockBrushFloorTab(iBaseBlock, iBlock, 0);
else
_setLuaBlockBrushFloorTab(iBlock, 0, 0);
}
}
void frmMain::_onParcelGallerySelect(wxRibbonGalleryEvent& evt)
{
if(evt.GetGalleryItem() != NULL)
{
_setLuaParcelBrush(static_cast<int>(reinterpret_cast<intptr_t>(
evt.GetGallery()->GetItemClientData(evt.GetGalleryItem()))));
}
}
void frmMain::_setLuaParcelBrush(int iParcel)
{
m_iParcelBrush = iParcel;
lua_State *L = m_pGamePanel->getLua();
luaT_execute(L, "_MAP_EDITOR:setBlockBrushParcel(...)", iParcel);
}
void frmMain::_onWallGallery1Select(wxRibbonGalleryEvent& evt)
{
if(evt.GetGalleryItem() != NULL)
{
m_pWallGallery2->SetSelection(NULL);
int iBlock = m_pWallGallery1->GetBlock(evt.GetGalleryItem(), NULL);
_setLuaBlockBrushWallsTab(0, 0, iBlock);
}
}
void frmMain::_onWallGallery2Select(wxRibbonGalleryEvent& evt)
{
if(evt.GetGalleryItem() != NULL)
{
m_pWallGallery1->SetSelection(NULL);
int iBlock = m_pWallGallery2->GetBlock(evt.GetGalleryItem(), NULL);
_setLuaBlockBrushWallsTab(0, iBlock, 0);
}
}
void frmMain::_setLuaBlockBrushFloorTab(int iBlockF, int iBlockW1, int iBlockW2)
{
m_iFloorTabBrushF = iBlockF;
m_iFloorTabBrushW1 = iBlockW1;
m_iFloorTabBrushW2 = iBlockW2;
_setLuaBlockBrushFloorTab();
}
void frmMain::_setLuaBlockBrushWallsTab(int iBlockF, int iBlockW1, int iBlockW2)
{
m_iWallsTabBrushF = iBlockF;
m_iWallsTabBrushW1 = iBlockW1;
m_iWallsTabBrushW2 = iBlockW2;
_setLuaBlockBrushWallsTab();
}
void frmMain::_setLuaBlockBrushFloorTab()
{
_setLuaBlockBrush(m_iFloorTabBrushF, m_iFloorTabBrushW1, m_iFloorTabBrushW2);
}
void frmMain::_setLuaBlockBrushWallsTab()
{
_setLuaBlockBrush(m_iWallsTabBrushF, m_iWallsTabBrushW1, m_iWallsTabBrushW2);
}
void frmMain::_setLuaBlockBrush(int iBlockF, int iBlockW1, int iBlockW2)
{
lua_State *L = m_pGamePanel->getLua();
luaT_execute(L, "_MAP_EDITOR:setBlockBrush(...)",
iBlockF, iBlockW1, iBlockW2);
}
void frmMain::_doLuaUndo()
{
lua_State *L = m_pGamePanel->getLua();
luaT_execute(L, "_MAP_EDITOR:undo()");
m_pGamePanel->Refresh();
}
void frmMain::_doLuaRedo()
{
lua_State *L = m_pGamePanel->getLua();
luaT_execute(L, "_MAP_EDITOR:redo()");
m_pGamePanel->Refresh();
}

View File

@@ -1,129 +0,0 @@
/*
Copyright (c) 2009 Peter "Corsix" Cawley
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once
// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
// for all others, include the necessary headers (this file is usually all you
// need because it includes almost all "standard" wxWidgets headers)
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
// ----------------------------
#include "scrollable_game.h"
#include <wx/ribbon/bar.h>
#include <wx/ribbon/buttonbar.h>
#include <wx/splitter.h>
#include "block_gallery.h"
class frmMain : public wxFrame
{
public:
frmMain();
~frmMain();
enum
{
ID_GALLERY_FLOOR1 = wxID_HIGHEST + 1,
ID_GALLERY_FLOOR2,
ID_GALLERY_WALL1,
ID_GALLERY_WALL2,
ID_GALLERY_PARCELS,
ID_VIEW_WALLS,
ID_VIEW_FLAGS,
ID_VIEW_PARCELS,
ID_VIEW_POSITIONS,
ID_PARCEL_PANEL,
ID_SAVE_IN_DROPDOWN,
ID_SAVEAS
};
protected:
wxRibbonBar* m_pRibbon;
wxRibbonPage* m_pHomePage;
frmLog* m_pLogWindow;
ScrollableGamePanel* m_pGamePanel;
RibbonBlockGallery* m_pFloorGallery1;
RibbonBlockGallery* m_pFloorGallery2;
RibbonBlockGallery* m_pWallGallery1;
RibbonBlockGallery* m_pWallGallery2;
wxString m_sFrameCaption;
wxString m_sFilename;
bool m_bViewFlags;
bool m_bViewParcels;
bool m_bViewPositions;
bool m_bViewWalls;
int m_iFloorTabBrushF;
int m_iFloorTabBrushW1;
int m_iFloorTabBrushW2;
int m_iWallsTabBrushF;
int m_iWallsTabBrushW1;
int m_iWallsTabBrushW2;
int m_iParcelBrush;
void _applyViewWalls();
void _applyViewOverlay();
wxString _getMapsDirectory();
wxString _getMapsFilter();
void _setFilename(const wxString& sFilename);
void _onFloorGallery1Select(wxRibbonGalleryEvent& evt);
void _onFloorGallery2Select(wxRibbonGalleryEvent& evt);
void _onWallGallery1Select(wxRibbonGalleryEvent& evt);
void _onWallGallery2Select(wxRibbonGalleryEvent& evt);
void _onParcelGallerySelect(wxRibbonGalleryEvent& evt);
void _onNew(wxRibbonButtonBarEvent& evt);
void _onOpen(wxRibbonButtonBarEvent& evt);
void _onSave(wxRibbonButtonBarEvent& evt);
void _onUndo(wxRibbonButtonBarEvent& evt);
void _onRedo(wxRibbonButtonBarEvent& evt);
void _onSaveMenu(wxRibbonButtonBarEvent& evt);
void _onSaveMenuSave(wxCommandEvent& evt);
void _onSaveMenuSaveAs(wxCommandEvent& evt);
void _onResize(wxSizeEvent& evt);
void _onViewWalls(wxRibbonButtonBarEvent& evt);
void _onViewFlags(wxRibbonButtonBarEvent& evt);
void _onViewParcels(wxRibbonButtonBarEvent& evt);
void _onViewPositions(wxRibbonButtonBarEvent& evt);
void _onRibbonPageChanged(wxRibbonBarEvent& evt);
void _populateParcelGallery(wxRibbonGallery* pGallery);
static wxBitmap _asBitmap(THSpriteSheet* pSheet, unsigned int iSprite);
static int _l_init(lua_State *L);
static int _l_init_with_lua_app(lua_State *L);
static int _l_set_blocks(lua_State *L);
static int _l_set_block_brush(lua_State *L);
static int _l_do_load(lua_State *L);
void _setLuaBlockBrushFloorTab(int iBlockF, int iBlockW1, int iBlockW2);
void _setLuaBlockBrushWallsTab(int iBlockF, int iBlockW1, int iBlockW2);
void _setLuaBlockBrushFloorTab();
void _setLuaBlockBrushWallsTab();
void _setLuaBlockBrush(int iBlockF, int iBlockW1, int iBlockW2);
void _setLuaParcelBrush(int iParcel);
void _doLuaUndo();
void _doLuaRedo();
DECLARE_EVENT_TABLE();
};

View File

@@ -1,31 +0,0 @@
/*
Copyright (c) 2009 Peter "Corsix" Cawley
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once
#include "config.h"
#ifndef CORSIX_TH_USE_OGL_RENDERER
#error To compile the map editor, the OpenGL rendering engine must be used
#endif
#include "../../CorsixTH/Src/th_gfx.h"
#include "../../CorsixTH/Src/th_lua.h"
#include "../../CorsixTH/Src/th_map.h"
#include "../../CorsixTH/Src/th_map_overlays.h"

View File

@@ -1,304 +0,0 @@
/*
Copyright (c) 2009 Peter "Corsix" Cawley
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <algorithm>
#include "scrollable_game.h"
BEGIN_EVENT_TABLE(ScrollableGamePanel, wxPanel)
EVT_SIZE(ScrollableGamePanel::_onResize)
EVT_COMMAND_SCROLL(ID_X_SCROLL, ScrollableGamePanel::_onScroll)
EVT_COMMAND_SCROLL(ID_Y_SCROLL, ScrollableGamePanel::_onScroll)
EVT_TIMER(wxID_ANY, ScrollableGamePanel::_onTimer)
END_EVENT_TABLE()
ScrollableGamePanel::ScrollableGamePanel(wxWindow *pParent)
: wxPanel(pParent)
, m_pGamePanel(NULL)
, m_pMapScrollX(NULL)
, m_pMapScrollY(NULL)
, m_bShouldRespondToScroll(true)
{
wxFlexGridSizer *pSizer = new wxFlexGridSizer(2, 2, 0, 0);
pSizer->AddGrowableRow(0, 1);
pSizer->AddGrowableCol(0, 1);
pSizer->Add(m_pGamePanel = new EmbeddedGamePanel(this), 1, wxEXPAND);
m_pGamePanel->setExtraLuaInitFunction(_l_extra_init,
reinterpret_cast<void*>(this));
pSizer->Add(m_pMapScrollY = new wxScrollBar(this, ID_Y_SCROLL,
wxDefaultPosition, wxDefaultSize, wxVERTICAL), 0, wxEXPAND);
pSizer->Add(m_pMapScrollX = new wxScrollBar(this, ID_X_SCROLL,
wxDefaultPosition, wxDefaultSize, wxHORIZONTAL), 0, wxEXPAND);
pSizer->AddSpacer(0);
m_pTimer = new wxTimer(this, wxID_ANY);
m_pTimer->Start(100, false);
SetSizer(pSizer);
}
ScrollableGamePanel::~ScrollableGamePanel()
{
m_pTimer->Stop();
}
void ScrollableGamePanel::setExtraLuaInitFunction(lua_CFunction fn, void* arg)
{
m_fnExtraInit = fn;
m_pExtraInitArg = arg;
}
void ScrollableGamePanel::setLogWindow(frmLog *pLogWindow)
{
m_pGamePanel->setLogWindow(pLogWindow);
}
bool ScrollableGamePanel::loadLua()
{
return m_pGamePanel->loadLua();
}
lua_State* ScrollableGamePanel::getLua()
{
return m_pGamePanel->getLua();
}
THMap* ScrollableGamePanel::getMap()
{
return m_pGamePanel->getMap();
}
void ScrollableGamePanel::_onResize(wxSizeEvent& evt)
{
lua_State *L = m_pGamePanel->getLua();
if(!L)
goto default_resize;
// Get old world-coordinates of window center
lua_Number fX, fY;
lua_getglobal(L, "TheApp");
if(lua_isnil(L, -1))
{
lua_pop(L, 1);
goto default_resize;
}
lua_getfield(L, -1, "ui");
if(lua_isnil(L, -1))
{
lua_pop(L, 2);
goto default_resize;
}
lua_getfield(L, -1, "ScreenToWorld");
lua_pushvalue(L, -2);
lua_pushinteger(L, m_pGamePanel->GetSize().GetWidth() / 2);
lua_pushinteger(L, m_pGamePanel->GetSize().GetHeight() / 2);
lua_call(L, 3, 2);
fX = lua_tonumber(L, -2) - 1.0;
fY = lua_tonumber(L, -1) - 1.0;
lua_pop(L, 2);
// Change window center
Layout();
// Move window center to same world co-ordinates
THMap::worldToScreen(fX, fY);
lua_getfield(L, -1, "scrollMapTo");
lua_insert(L, -2);
lua_pushnumber(L, fX);
lua_pushnumber(L, fY);
lua_call(L, 3, 0);
lua_pop(L, 1);
return;
default_resize:
evt.Skip();
}
int ScrollableGamePanel::_l_extra_init(lua_State *L)
{
ScrollableGamePanel* pThis = reinterpret_cast<ScrollableGamePanel*>(
lua_touserdata(L, 1));
// Perform the original extra initialisation
if(pThis->m_fnExtraInit != NULL)
{
if(lua_cpcall(L, pThis->m_fnExtraInit, pThis->m_pExtraInitArg) != 0)
lua_pop(L, 1);
}
// Hook around the MapEditorInitWithLuaApp function
lua_getglobal(L, "MapEditorInitWithLuaApp");
lua_pushvalue(L, 1);
lua_pushcclosure(L, _l_init_with_app, 2);
lua_setglobal(L, "MapEditorInitWithLuaApp");
return 0;
}
int ScrollableGamePanel::_l_init_with_app(lua_State *L)
{
// Call the original MapEditorInitWithLuaApp function
lua_pushvalue(L, lua_upvalueindex(1));
if(lua_type(L, -1) == LUA_TNIL)
lua_pop(L, 1);
else
{
lua_insert(L, 1);
lua_call(L, lua_gettop(L) - 1, LUA_MULTRET);
}
// Wrap our _l_on_ui_scroll_map function around GameUI:scrollMap()
// 1st upvalue: original GameUI:scrollMap() function
// 2nd upvalue: light userdata this
// This has to be done with the Lua App initialisation as we need for
// dofile() to be the custom dofile() used by CorsixTH, rather than the
// default one present at Lua initialisation time.
luaT_execute(L, "dofile [[game_ui]]");
lua_getglobal(L, "GameUI");
lua_getfield(L, -1, "scrollMap");
lua_pushvalue(L, lua_upvalueindex(2));
lua_pushcclosure(L, _l_on_ui_scroll_map, 2);
lua_setfield(L, -2, "scrollMap");
return lua_gettop(L);
}
int ScrollableGamePanel::_l_on_ui_scroll_map(lua_State *L)
{
ScrollableGamePanel *pThis = reinterpret_cast<ScrollableGamePanel*>(
lua_touserdata(L, lua_upvalueindex(2)));
// Make a copy of the "self" parameter at the bottom of the stack
lua_pushvalue(L, 1);
lua_insert(L, 1);
// Call original GameUI:scrollMap() function
lua_pushvalue(L, lua_upvalueindex(1));
lua_insert(L, 2);
lua_call(L, lua_gettop(L) - 2, LUA_MULTRET);
if(pThis->m_bShouldRespondToScroll)
{
int iPanelW, iPanelH;
pThis->m_pGamePanel->GetSize(&iPanelW, &iPanelH);
// Get world co-ordinates of window center
lua_checkstack(L, 4);
lua_getfield(L, 1, "ScreenToWorld");
lua_pushvalue(L, 1);
lua_pushinteger(L, iPanelW / 2);
lua_pushinteger(L, iPanelH / 2);
lua_call(L, 3, 2);
lua_Number fX = lua_tonumber(L, -2) - 1.0;
lua_Number fY = lua_tonumber(L, -1) - 1.0;
lua_pop(L, 2);
// Get map extents
THMap* pMap = pThis->m_pGamePanel->getMap();
int iMapH = pMap->getHeight();
int iTemp = pMap->getWidth();
pMap->worldToScreen(iTemp, iMapH);
int iMapW = pMap->getWidth();
iTemp = 0;
pMap->worldToScreen(iMapW, iTemp);
// Get screen co-ordinates of window center
// We could get these directly from the GameUI, but we'd be delving into
// its member variables, and also perhaps not properly accounting for zoom.
pMap->worldToScreen(fX, fY);
int iX = (int)fX;
int iY = (int)fY;
// Update scrollbars
pThis->m_pMapScrollX->SetScrollbar(iX + iMapW, iPanelW, iMapW * 2 + iPanelW, iPanelW);
pThis->m_pMapScrollY->SetScrollbar(iY , iPanelH, iMapH + iPanelH, iPanelH);
}
// Return results from original call
return lua_gettop(L) - 1;
}
void ScrollableGamePanel::_onScroll(wxScrollEvent& evt)
{
_positionMap();
}
void ScrollableGamePanel::_onTimer(wxTimerEvent& evt)
{
const int KEY_SENSITIVITY = 20;
int x = m_pMapScrollX->GetThumbPosition();
int y = m_pMapScrollY->GetThumbPosition();
bool bChanges = false;
if(wxGetKeyState(WXK_LEFT))
{
m_pMapScrollX->SetThumbPosition(std::max(0, x - KEY_SENSITIVITY));
bChanges = true;
}
if(wxGetKeyState(WXK_RIGHT))
{
m_pMapScrollX->SetThumbPosition(std::min(m_pMapScrollX->GetRange(), x + KEY_SENSITIVITY));
bChanges = true;
}
if(wxGetKeyState(WXK_UP))
{
m_pMapScrollY->SetThumbPosition(std::max(0, y - KEY_SENSITIVITY));
bChanges = true;
}
if(wxGetKeyState(WXK_DOWN))
{
m_pMapScrollY->SetThumbPosition(std::min(m_pMapScrollY->GetRange(), y + KEY_SENSITIVITY));
bChanges = true;
}
if (bChanges)
{
_positionMap();
}
}
void ScrollableGamePanel::_positionMap()
{
lua_State *L = getLua();
if(!L)
{
return;
}
lua_getglobal(L, "TheApp");
if(lua_isnil(L, -1))
{
lua_pop(L, 1);
return;
}
lua_getfield(L, -1, "ui");
if(lua_isnil(L, -1))
{
lua_pop(L, 2);
return;
}
lua_replace(L, -2);
lua_getfield(L, -1, "scrollMapTo");
lua_insert(L, -2);
lua_pushinteger(L, m_pMapScrollX->GetThumbPosition() - m_pMapScrollX->GetRange() / 2 + m_pMapScrollX->GetThumbSize() / 2);
lua_pushinteger(L, m_pMapScrollY->GetThumbPosition());
m_bShouldRespondToScroll = false;
lua_call(L, 3, 1);
m_bShouldRespondToScroll = true;
m_pGamePanel->Refresh(false);
}

View File

@@ -1,79 +0,0 @@
/*
Copyright (c) 2010 Peter "Corsix" Cawley
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once
// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
// for all others, include the necessary headers (this file is usually all you
// need because it includes almost all "standard" wxWidgets headers)
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
// ----------------------------
#include "embedded_game.h"
class ScrollableGamePanel : public wxPanel, public IEmbeddedGamePanel
{
public:
ScrollableGamePanel(wxWindow *pParent);
~ScrollableGamePanel();
void setExtraLuaInitFunction(lua_CFunction fn, void* arg);
void setLogWindow(frmLog *pLogWindow);
bool loadLua();
lua_State* getLua();
THMap* getMap();
enum
{
ID_X_SCROLL = wxID_HIGHEST + 1,
ID_Y_SCROLL
};
protected:
EmbeddedGamePanel* m_pGamePanel;
wxScrollBar* m_pMapScrollX;
wxScrollBar* m_pMapScrollY;
lua_CFunction m_fnExtraInit;
void* m_pExtraInitArg;
bool m_bShouldRespondToScroll;
wxTimer* m_pTimer;
void _onResize(wxSizeEvent& evt);
void _onScroll(wxScrollEvent& evt);
void _onTimer(wxTimerEvent& evt);
static int _l_extra_init(lua_State *L);
static int _l_init_with_app(lua_State *L);
static int _l_on_ui_scroll_map(lua_State *L);
DECLARE_EVENT_TABLE();
private:
void _positionMap();
};

View File

@@ -1,391 +0,0 @@
/*
Copyright (c) 2010 Peter "Corsix" Cawley
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "th_map_wrapper.h"
#include <stack>
#include <utility>
void THMapWrapper::autoSetHelipad(THMap *pMap)
{
// Search the map for a "H" pattern made up from two ground tiles.
// xxxxx
// xHxHx
// xHHHx
// xHxHx
// xxxxx
for(int iX = 2; iX < pMap->getWidth() - 2; ++iX)
{
for(int iY = 2; iY < pMap->getHeight() - 2; ++iY)
{
THMapNode *pNode = pMap->getNodeUnchecked(iX, iY);
if((pNode->iBlock[1] | pNode->iBlock[2]) & 0xFF)
continue;
uint16_t iFloor1 = pNode->iBlock[0] & 0xFF;
uint16_t iFloor2 = pNode[-2].iBlock[0] & 0xFF;
if(iFloor1 == iFloor2)
continue;
for(int iDX = -2; iDX <= 2; ++iDX)
{
for(int iDY = -2; iDY <= 2; ++iDY)
{
pNode = pMap->getNodeUnchecked(iX + iDX, iY + iDY);
if(-1 <= iDX && iDX <= 1 && -1 <= iDY && iDY <= 1)
{
if((iDX | iDY) == 0)
continue;
if((pNode->iBlock[1] | pNode->iBlock[2]) & 0xFF)
goto next_xy;
if((pNode->iBlock[0] & 0xFF) !=
(iDX == 0 ? iFloor2 : iFloor1))
{
goto next_xy;
}
}
else
{
if((pNode->iBlock[0] & 0xFF) != iFloor2)
goto next_xy;
}
}
}
pMap->setPlayerHeliportTile(0, iX, iY);
return;
next_xy:;
}
}
}
void THMapWrapper::wrap(lua_State *L)
{
luaT_execute(L, "require[[TH]].map.setCell = ...", _l_set_cell);
}
int THMapWrapper::_l_set_cell(lua_State *L)
{
// Perform same argument handling as normal setCell function
THMap* pMap = reinterpret_cast<THMap*>(lua_touserdata(L, 1));
int iX = luaL_checkint(L, 2) - 1; // Lua arrays start at 1 - pretend
int iY = luaL_checkint(L, 3) - 1; // the map does too.
THMapNode* pNode = pMap->getNode(iX, iY);
if(pNode == NULL)
return luaL_argerror(L, 2, "Map co-ordinates out of bounds");
uint16_t iNewBlocks[4] = {
pNode->iBlock[0],
pNode->iBlock[1],
pNode->iBlock[2],
pNode->iBlock[3]
};
if(lua_gettop(L) >= 7)
{
iNewBlocks[0] = (uint16_t)luaL_checkint(L, 4);
iNewBlocks[1] = (uint16_t)luaL_checkint(L, 5);
iNewBlocks[2] = (uint16_t)luaL_checkint(L, 6);
iNewBlocks[3] = (uint16_t)luaL_checkint(L, 7);
}
else
{
int iLayer = luaL_checkint(L, 4) - 1;
if(iLayer < 0 || iLayer >= 4)
return luaL_argerror(L, 4, "Layer index is out of bounds (1-4)");
int iBlock = luaL_checkint(L, 5);
iNewBlocks[iLayer] = (uint16_t)iBlock;
}
// Dispatch the call
_do_set_cell(L, pMap, iX, iY, iNewBlocks);
lua_settop(L, 1);
return 1;
}
bool THMapWrapper::_isDoorframe(int iTile)
{
return ms_iDoorframeWallFirst <= iTile && iTile <= ms_iDoorframeWallLast;
}
bool THMapWrapper::_isPassable(int iTile)
{
iTile &= 0xFF;
if(iTile <= 5)
return iTile >= 4;
else if(iTile <= 0x17)
return iTile >= 0xF;
else if(iTile <= 0x3A)
return iTile >= 0x29;
else
return iTile == 0x42 || iTile == 0x46 || iTile == 0x4C;
}
bool THMapWrapper::_isWall(int iTile)
{
iTile &= 0xFF;
if(82 <= iTile && iTile <= 155)
return true;
// NB: 157 through 160 are walls, but not the purposes of defining
// hospital tiles.
if(161 <= iTile && iTile <= 164)
return true;
return false;
}
bool THMapWrapper::_isCertainlyHospital(THMap* pMap, int iX, int iY)
{
THMapNode *pNode = pMap->getNode(iX, iY);
if(pNode && (pNode->iFlags & THMN_Passable))
{
if(_isWall(pNode->iBlock[1]) || _isWall(pNode->iBlock[2]))
return true;
THMapNode *pNeighbour = pMap->getNode(iX, iY + 1);
if(pNeighbour && _isWall(pNeighbour->iBlock[1]))
return true;
pNeighbour = pMap->getNode(iX + 1, iY);
if(pNeighbour && _isWall(pNeighbour->iBlock[2]))
return true;
}
return false;
}
void THMapWrapper::_do_set_cell(lua_State *L, THMap* pMap, int iX, int iY, uint16_t iNewBlocks[4])
{
THMapNode *pNode = pMap->getNodeUnchecked(iX, iY);
bool bShouldCheckHospitality = false;
bool bWasCertainlyHospital = _isCertainlyHospital(pMap, iX, iY);
// Check for wall blocks which should have sliding doors
bool bShouldCheckNeighbourDoors = false;
bool bShouldCheckOwnDoor = false;
for(int iDir = 0; iDir <= 1; ++iDir)
{
uint16_t iOld = pNode->iBlock[1 + iDir] & 0xFF;
uint16_t iNew = iNewBlocks[1 + iDir] & 0xFF;
if(iOld == iNew)
continue;
bShouldCheckHospitality = true;
if(_isDoorframe(iOld) || _isDoorframe(iNew))
bShouldCheckNeighbourDoors = true;
if((iOld == 0) != (iNew == 0))
bShouldCheckOwnDoor = true;
}
uint32_t iOldFlags = pNode->iFlags;
if(_isPassable(iNewBlocks[0]))
pNode->iFlags |= THMN_Passable;
else
pNode->iFlags &=~ THMN_Passable;
if(pNode->iFlags != iOldFlags)
bShouldCheckHospitality = true;
pNode->iBlock[0] = iNewBlocks[0];
pNode->iBlock[1] = iNewBlocks[1];
pNode->iBlock[2] = iNewBlocks[2];
pNode->iBlock[3] = iNewBlocks[3];
if(bShouldCheckOwnDoor)
{
_check_door(L, pMap, iX, iY, 1, 0) ||
_check_door(L, pMap, iX, iY, 0, 1);
}
if(bShouldCheckNeighbourDoors)
{
_check_door(L, pMap, iX - 1, iY , 1, 0);
_check_door(L, pMap, iX , iY - 1, 0, 1);
_check_door(L, pMap, iX + 1, iY , 1, 0);
_check_door(L, pMap, iX , iY + 1, 0, 1);
}
std::stack<std::pair<int, int> > stkToCheckHospitality;
if(bWasCertainlyHospital && !_isCertainlyHospital(pMap, iX, iY))
{
std::stack<std::pair<int, int> > stkToRemoveHospitality;
stkToRemoveHospitality.push(std::make_pair(iX, iY));
while(!stkToRemoveHospitality.empty())
{
int iX = stkToRemoveHospitality.top().first;
int iY = stkToRemoveHospitality.top().second;
stkToRemoveHospitality.pop();
THMapNode *pNode = pMap->getNode(iX, iY);
if(pNode && (pNode->iFlags & THMN_Hospital) != 0
&& !_isCertainlyHospital(pMap, iX, iY))
{
stkToCheckHospitality.push(std::make_pair(iX, iY));
pNode->iFlags &=~ THMN_Hospital;
for(int iDir = 0; iDir <= 1; ++iDir)
{
for(int iDelta = -1; iDelta <= 1; iDelta += 2)
{
stkToRemoveHospitality.push(std::make_pair(
iX + iDelta * iDir, iY + iDelta * (1 - iDir)));
}
}
}
}
}
if(bShouldCheckHospitality)
{
stkToCheckHospitality.push(std::make_pair(iX, iY));
stkToCheckHospitality.push(std::make_pair(iX - 1, iY ));
stkToCheckHospitality.push(std::make_pair(iX , iY - 1));
}
if(!stkToCheckHospitality.empty())
pMap->updatePathfinding();
while(!stkToCheckHospitality.empty())
{
int iX = stkToCheckHospitality.top().first;
int iY = stkToCheckHospitality.top().second;
stkToCheckHospitality.pop();
THMapNode *pNode = pMap->getNode(iX, iY);
if(!pNode)
continue;
bool bShouldBeHospital = false;
if(pNode->iFlags & THMN_Passable)
{
bShouldBeHospital = _isCertainlyHospital(pMap, iX, iY);
int iNumHospitalNeighbours = 0;
#define CHECK(dir_flag, dx, dy) \
if(pNode->iFlags & dir_flag) \
{ \
iNumHospitalNeighbours += (pMap->getNode(iX + dx, iY + dy) \
->iFlags & THMN_Hospital) >> THMN_Hospital_Shift; \
}
CHECK(THMN_CanTravelN, 0, -1);
CHECK(THMN_CanTravelE, 1, 0);
CHECK(THMN_CanTravelS, 0, 1);
CHECK(THMN_CanTravelW, -1, 0);
#undef CHECK
if(iNumHospitalNeighbours >= 2)
bShouldBeHospital = true;
}
if(bShouldBeHospital != ((pNode->iFlags & THMN_Hospital) != 0))
{
if(bShouldBeHospital)
{
pNode->iFlags |= THMN_Hospital;
_check_door_unbuildability(pMap, iX, iY);
}
else
pNode->iFlags &=~ (THMN_Hospital | THMN_Buildable);
for(int iDir = 0; iDir <= 1; ++iDir)
{
for(int iDelta = -1; iDelta <= 1; iDelta += 2)
{
stkToCheckHospitality.push(std::make_pair(
iX + iDelta * iDir, iY + iDelta * (1 - iDir)));
}
}
}
}
}
void THMapWrapper::_check_door_unbuildability(THMap* pMap, int iX, int iY)
{
THMapNode *pNode = pMap->getNode(iX, iY);
if(!pNode)
return;
bool bBuildable = (pNode->iFlags & THMN_Hospital) != 0;
for(int iDX = -1; iDX <= 1; ++iDX)
{
for(int iDY = -1; iDY <= 1; ++iDY)
{
THMapNode *pNode = pMap->getNode(iX + iDX, iY + iDY);
if(!pNode || (pNode->iFlags >> 24) != THOB_EntranceRightDoor)
continue;
bool bIsNorthFacing = (pNode[-1].iFlags >> 24) == THOB_EntranceLeftDoor;
if(bIsNorthFacing)
{
if(iDY != -1)
bBuildable = false;
}
else
{
if(iDX != -1)
bBuildable = false;
}
}
}
if(bBuildable)
pNode->iFlags |= THMN_Buildable;
else
pNode->iFlags &=~ THMN_Buildable;
}
bool THMapWrapper::_check_door(lua_State *L, THMap* pMap, int iX, int iY, int iDX, int iDY)
{
bool bShouldHaveDoor = false;
THMapNode *pNode = pMap->getNode(iX, iY);
if(pNode && !(pNode->iBlock[1] & 0xFF) && !(pNode->iBlock[2] & 0xFF))
{
THMapNode *pFarNode = pMap->getNode(iX - iDX, iY - iDY);
THMapNode *pNearNode = pMap->getNode(iX + iDX, iY + iDY);
if(pFarNode && pNearNode)
{
int iFarBlock = pFarNode->iBlock[1 + iDY] & 0xFF;
int iNearBlock = pNearNode->iBlock[1 + iDY] & 0xFF;
if(iFarBlock == ms_iDoorframeFarExternal + iDY
|| iFarBlock == ms_iDoorframeFarInternal + iDY)
{
if(iNearBlock == ms_iDoorframeNearExternal + iDY
|| iNearBlock == ms_iDoorframeNearInternal + iDY)
{
bShouldHaveDoor = true;
}
}
}
}
THObjectType eNodeThob = (THObjectType)(pNode->iFlags >> 24);
bool bGotDoor = eNodeThob == THOB_EntranceLeftDoor ||
eNodeThob == THOB_EntranceRightDoor;
if(bGotDoor == bShouldHaveDoor)
{
return false;
}
else if(bShouldHaveDoor)
{
for(int i = 1; i >= 0; --i)
{
luaT_execute(L, "TheApp.world:newObject(...)",
i == 1 ? "entrance_left_door" : "entrance_right_door",
iX + 1 - i * iDX,
iY + 1 - i * iDY,
iDX == 1 ? "north" : "west");
}
}
else
{
luaT_execute(L,
"local world = TheApp.world\n"
"local door = world:getObject(...)\n"
"if door then world:destroyEntity(door)\n"
"if door.slave then world:destroyEntity(door.slave) end end\n",
iX + 1,
iY + 1);
}
for(int iDX = -1; iDX <= 1; ++iDX)
{
for(int iDY = -1; iDY <= 1; ++iDY)
{
_check_door_unbuildability(pMap, iX + iDX, iY + iDY);
}
}
return bShouldHaveDoor;
}

View File

@@ -1,70 +0,0 @@
/*
Copyright (c) 2010 Peter "Corsix" Cawley
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once
// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
// for all others, include the necessary headers (this file is usually all you
// need because it includes almost all "standard" wxWidgets headers)
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
// ----------------------------
#include "game.h"
class THMapWrapper
{
public:
//! Wrap around the Map class of a Lua state
/*!
This should be called at the initialisation time of a Lua state (after
luaopen_th has been registered to package.preload, but before any map
instances have been created). After calling, all map instances created
by the state will have this wrapper around them.
*/
static void wrap(lua_State *L);
static void autoSetHelipad(THMap *pMap);
protected:
static int _l_set_cell(lua_State *L);
static void _do_set_cell(lua_State *L, THMap* pMap, int iX, int iY, uint16_t iNewBlocks[4]);
static bool _check_door(lua_State *L, THMap* pMap, int iX, int iY, int iDX, int iDY);
static void _check_door_unbuildability(THMap* pMap, int iX, int iY);
static const int ms_iDoorframeWallFirst = 157;
static const int ms_iDoorframeNearExternal = 157;
static const int ms_iDoorframeFarExternal = 159;
static const int ms_iDoorframeNearInternal = 161;
static const int ms_iDoorframeFarInternal = 163;
static const int ms_iDoorframeWallLast = 164;
static bool _isDoorframe(int iTile);
static bool _isPassable(int iTile);
static bool _isWall(int iTile);
static bool _isCertainlyHospital(THMap* pMap, int iX, int iY);
};