Updated almost all stuff
744
.clang-format
Normal file
@@ -0,0 +1,744 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
#
|
||||
# clang-format configuration file. Intended for clang-format >= 11.
|
||||
#
|
||||
# For more information, see:
|
||||
#
|
||||
# Documentation/process/clang-format.rst
|
||||
# https://clang.llvm.org/docs/ClangFormat.html
|
||||
# https://clang.llvm.org/docs/ClangFormatStyleOptions.html
|
||||
#
|
||||
---
|
||||
AccessModifierOffset: -8
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
AlignEscapedNewlines: Left
|
||||
AlignOperands: true
|
||||
AlignTrailingComments: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortBlocksOnASingleLine: false
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: None
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: false
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BraceWrapping:
|
||||
AfterClass: false
|
||||
AfterControlStatement: false
|
||||
AfterEnum: false
|
||||
AfterFunction: true
|
||||
AfterNamespace: true
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
AfterExternBlock: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Custom
|
||||
BreakBeforeInheritanceComma: false
|
||||
BreakBeforeTernaryOperators: false
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BreakConstructorInitializers: BeforeComma
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: false
|
||||
ColumnLimit: 80
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
ConstructorInitializerIndentWidth: 8
|
||||
ContinuationIndentWidth: 8
|
||||
Cpp11BracedListStyle: false
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
FixNamespaceComments: false
|
||||
|
||||
# Taken from:
|
||||
# git grep -h '^#define [^[:space:]]*for_each[^[:space:]]*(' include/ tools/ \
|
||||
# | sed "s,^#define \([^[:space:]]*for_each[^[:space:]]*\)(.*$, - '\1'," \
|
||||
# | LC_ALL=C sort -u
|
||||
ForEachMacros:
|
||||
- '__ata_qc_for_each'
|
||||
- '__bio_for_each_bvec'
|
||||
- '__bio_for_each_segment'
|
||||
- '__evlist__for_each_entry'
|
||||
- '__evlist__for_each_entry_continue'
|
||||
- '__evlist__for_each_entry_from'
|
||||
- '__evlist__for_each_entry_reverse'
|
||||
- '__evlist__for_each_entry_safe'
|
||||
- '__for_each_mem_range'
|
||||
- '__for_each_mem_range_rev'
|
||||
- '__for_each_thread'
|
||||
- '__hlist_for_each_rcu'
|
||||
- '__map__for_each_symbol_by_name'
|
||||
- '__pci_bus_for_each_res0'
|
||||
- '__pci_bus_for_each_res1'
|
||||
- '__pci_dev_for_each_res0'
|
||||
- '__pci_dev_for_each_res1'
|
||||
- '__perf_evlist__for_each_entry'
|
||||
- '__perf_evlist__for_each_entry_reverse'
|
||||
- '__perf_evlist__for_each_entry_safe'
|
||||
- '__rq_for_each_bio'
|
||||
- '__shost_for_each_device'
|
||||
- '__sym_for_each'
|
||||
- 'apei_estatus_for_each_section'
|
||||
- 'ata_for_each_dev'
|
||||
- 'ata_for_each_link'
|
||||
- 'ata_qc_for_each'
|
||||
- 'ata_qc_for_each_raw'
|
||||
- 'ata_qc_for_each_with_internal'
|
||||
- 'ax25_for_each'
|
||||
- 'ax25_uid_for_each'
|
||||
- 'bio_for_each_bvec'
|
||||
- 'bio_for_each_bvec_all'
|
||||
- 'bio_for_each_folio_all'
|
||||
- 'bio_for_each_integrity_vec'
|
||||
- 'bio_for_each_segment'
|
||||
- 'bio_for_each_segment_all'
|
||||
- 'bio_list_for_each'
|
||||
- 'bip_for_each_vec'
|
||||
- 'bond_for_each_slave'
|
||||
- 'bond_for_each_slave_rcu'
|
||||
- 'bpf_for_each'
|
||||
- 'bpf_for_each_reg_in_vstate'
|
||||
- 'bpf_for_each_reg_in_vstate_mask'
|
||||
- 'bpf_for_each_spilled_reg'
|
||||
- 'bpf_object__for_each_map'
|
||||
- 'bpf_object__for_each_program'
|
||||
- 'btree_for_each_safe128'
|
||||
- 'btree_for_each_safe32'
|
||||
- 'btree_for_each_safe64'
|
||||
- 'btree_for_each_safel'
|
||||
- 'card_for_each_dev'
|
||||
- 'cgroup_taskset_for_each'
|
||||
- 'cgroup_taskset_for_each_leader'
|
||||
- 'cpu_aggr_map__for_each_idx'
|
||||
- 'cpufreq_for_each_efficient_entry_idx'
|
||||
- 'cpufreq_for_each_entry'
|
||||
- 'cpufreq_for_each_entry_idx'
|
||||
- 'cpufreq_for_each_valid_entry'
|
||||
- 'cpufreq_for_each_valid_entry_idx'
|
||||
- 'css_for_each_child'
|
||||
- 'css_for_each_descendant_post'
|
||||
- 'css_for_each_descendant_pre'
|
||||
- 'damon_for_each_region'
|
||||
- 'damon_for_each_region_from'
|
||||
- 'damon_for_each_region_safe'
|
||||
- 'damon_for_each_scheme'
|
||||
- 'damon_for_each_scheme_safe'
|
||||
- 'damon_for_each_target'
|
||||
- 'damon_for_each_target_safe'
|
||||
- 'damos_for_each_filter'
|
||||
- 'damos_for_each_filter_safe'
|
||||
- 'data__for_each_file'
|
||||
- 'data__for_each_file_new'
|
||||
- 'data__for_each_file_start'
|
||||
- 'device_for_each_child_node'
|
||||
- 'displayid_iter_for_each'
|
||||
- 'dma_fence_array_for_each'
|
||||
- 'dma_fence_chain_for_each'
|
||||
- 'dma_fence_unwrap_for_each'
|
||||
- 'dma_resv_for_each_fence'
|
||||
- 'dma_resv_for_each_fence_unlocked'
|
||||
- 'do_for_each_ftrace_op'
|
||||
- 'drm_atomic_crtc_for_each_plane'
|
||||
- 'drm_atomic_crtc_state_for_each_plane'
|
||||
- 'drm_atomic_crtc_state_for_each_plane_state'
|
||||
- 'drm_atomic_for_each_plane_damage'
|
||||
- 'drm_client_for_each_connector_iter'
|
||||
- 'drm_client_for_each_modeset'
|
||||
- 'drm_connector_for_each_possible_encoder'
|
||||
- 'drm_exec_for_each_locked_object'
|
||||
- 'drm_exec_for_each_locked_object_reverse'
|
||||
- 'drm_for_each_bridge_in_chain'
|
||||
- 'drm_for_each_connector_iter'
|
||||
- 'drm_for_each_crtc'
|
||||
- 'drm_for_each_crtc_reverse'
|
||||
- 'drm_for_each_encoder'
|
||||
- 'drm_for_each_encoder_mask'
|
||||
- 'drm_for_each_fb'
|
||||
- 'drm_for_each_legacy_plane'
|
||||
- 'drm_for_each_plane'
|
||||
- 'drm_for_each_plane_mask'
|
||||
- 'drm_for_each_privobj'
|
||||
- 'drm_gem_for_each_gpuva'
|
||||
- 'drm_gem_for_each_gpuva_safe'
|
||||
- 'drm_gpuva_for_each_op'
|
||||
- 'drm_gpuva_for_each_op_from_reverse'
|
||||
- 'drm_gpuva_for_each_op_safe'
|
||||
- 'drm_gpuvm_for_each_va'
|
||||
- 'drm_gpuvm_for_each_va_range'
|
||||
- 'drm_gpuvm_for_each_va_range_safe'
|
||||
- 'drm_gpuvm_for_each_va_safe'
|
||||
- 'drm_mm_for_each_hole'
|
||||
- 'drm_mm_for_each_node'
|
||||
- 'drm_mm_for_each_node_in_range'
|
||||
- 'drm_mm_for_each_node_safe'
|
||||
- 'dsa_switch_for_each_available_port'
|
||||
- 'dsa_switch_for_each_cpu_port'
|
||||
- 'dsa_switch_for_each_cpu_port_continue_reverse'
|
||||
- 'dsa_switch_for_each_port'
|
||||
- 'dsa_switch_for_each_port_continue_reverse'
|
||||
- 'dsa_switch_for_each_port_safe'
|
||||
- 'dsa_switch_for_each_user_port'
|
||||
- 'dsa_tree_for_each_cpu_port'
|
||||
- 'dsa_tree_for_each_user_port'
|
||||
- 'dsa_tree_for_each_user_port_continue_reverse'
|
||||
- 'dso__for_each_symbol'
|
||||
- 'dsos__for_each_with_build_id'
|
||||
- 'elf_hash_for_each_possible'
|
||||
- 'elf_symtab__for_each_symbol'
|
||||
- 'evlist__for_each_cpu'
|
||||
- 'evlist__for_each_entry'
|
||||
- 'evlist__for_each_entry_continue'
|
||||
- 'evlist__for_each_entry_from'
|
||||
- 'evlist__for_each_entry_reverse'
|
||||
- 'evlist__for_each_entry_safe'
|
||||
- 'flow_action_for_each'
|
||||
- 'for_each_acpi_consumer_dev'
|
||||
- 'for_each_acpi_dev_match'
|
||||
- 'for_each_active_dev_scope'
|
||||
- 'for_each_active_drhd_unit'
|
||||
- 'for_each_active_iommu'
|
||||
- 'for_each_active_route'
|
||||
- 'for_each_aggr_pgid'
|
||||
- 'for_each_and_bit'
|
||||
- 'for_each_andnot_bit'
|
||||
- 'for_each_available_child_of_node'
|
||||
- 'for_each_bench'
|
||||
- 'for_each_bio'
|
||||
- 'for_each_board_func_rsrc'
|
||||
- 'for_each_btf_ext_rec'
|
||||
- 'for_each_btf_ext_sec'
|
||||
- 'for_each_bvec'
|
||||
- 'for_each_card_auxs'
|
||||
- 'for_each_card_auxs_safe'
|
||||
- 'for_each_card_components'
|
||||
- 'for_each_card_dapms'
|
||||
- 'for_each_card_pre_auxs'
|
||||
- 'for_each_card_prelinks'
|
||||
- 'for_each_card_rtds'
|
||||
- 'for_each_card_rtds_safe'
|
||||
- 'for_each_card_widgets'
|
||||
- 'for_each_card_widgets_safe'
|
||||
- 'for_each_cgroup_storage_type'
|
||||
- 'for_each_child_of_node'
|
||||
- 'for_each_clear_bit'
|
||||
- 'for_each_clear_bit_from'
|
||||
- 'for_each_clear_bitrange'
|
||||
- 'for_each_clear_bitrange_from'
|
||||
- 'for_each_cmd'
|
||||
- 'for_each_cmsghdr'
|
||||
- 'for_each_collection'
|
||||
- 'for_each_comp_order'
|
||||
- 'for_each_compatible_node'
|
||||
- 'for_each_component_dais'
|
||||
- 'for_each_component_dais_safe'
|
||||
- 'for_each_conduit'
|
||||
- 'for_each_console'
|
||||
- 'for_each_console_srcu'
|
||||
- 'for_each_cpu'
|
||||
- 'for_each_cpu_and'
|
||||
- 'for_each_cpu_andnot'
|
||||
- 'for_each_cpu_or'
|
||||
- 'for_each_cpu_wrap'
|
||||
- 'for_each_dapm_widgets'
|
||||
- 'for_each_dedup_cand'
|
||||
- 'for_each_dev_addr'
|
||||
- 'for_each_dev_scope'
|
||||
- 'for_each_dma_cap_mask'
|
||||
- 'for_each_dpcm_be'
|
||||
- 'for_each_dpcm_be_rollback'
|
||||
- 'for_each_dpcm_be_safe'
|
||||
- 'for_each_dpcm_fe'
|
||||
- 'for_each_drhd_unit'
|
||||
- 'for_each_dss_dev'
|
||||
- 'for_each_efi_memory_desc'
|
||||
- 'for_each_efi_memory_desc_in_map'
|
||||
- 'for_each_element'
|
||||
- 'for_each_element_extid'
|
||||
- 'for_each_element_id'
|
||||
- 'for_each_endpoint_of_node'
|
||||
- 'for_each_event'
|
||||
- 'for_each_event_tps'
|
||||
- 'for_each_evictable_lru'
|
||||
- 'for_each_fib6_node_rt_rcu'
|
||||
- 'for_each_fib6_walker_rt'
|
||||
- 'for_each_free_mem_pfn_range_in_zone'
|
||||
- 'for_each_free_mem_pfn_range_in_zone_from'
|
||||
- 'for_each_free_mem_range'
|
||||
- 'for_each_free_mem_range_reverse'
|
||||
- 'for_each_func_rsrc'
|
||||
- 'for_each_gpiochip_node'
|
||||
- 'for_each_group_evsel'
|
||||
- 'for_each_group_evsel_head'
|
||||
- 'for_each_group_member'
|
||||
- 'for_each_group_member_head'
|
||||
- 'for_each_hstate'
|
||||
- 'for_each_if'
|
||||
- 'for_each_inject_fn'
|
||||
- 'for_each_insn'
|
||||
- 'for_each_insn_prefix'
|
||||
- 'for_each_intid'
|
||||
- 'for_each_iommu'
|
||||
- 'for_each_ip_tunnel_rcu'
|
||||
- 'for_each_irq_nr'
|
||||
- 'for_each_lang'
|
||||
- 'for_each_link_codecs'
|
||||
- 'for_each_link_cpus'
|
||||
- 'for_each_link_platforms'
|
||||
- 'for_each_lru'
|
||||
- 'for_each_matching_node'
|
||||
- 'for_each_matching_node_and_match'
|
||||
- 'for_each_media_entity_data_link'
|
||||
- 'for_each_mem_pfn_range'
|
||||
- 'for_each_mem_range'
|
||||
- 'for_each_mem_range_rev'
|
||||
- 'for_each_mem_region'
|
||||
- 'for_each_member'
|
||||
- 'for_each_memory'
|
||||
- 'for_each_migratetype_order'
|
||||
- 'for_each_missing_reg'
|
||||
- 'for_each_mle_subelement'
|
||||
- 'for_each_mod_mem_type'
|
||||
- 'for_each_net'
|
||||
- 'for_each_net_continue_reverse'
|
||||
- 'for_each_net_rcu'
|
||||
- 'for_each_netdev'
|
||||
- 'for_each_netdev_continue'
|
||||
- 'for_each_netdev_continue_rcu'
|
||||
- 'for_each_netdev_continue_reverse'
|
||||
- 'for_each_netdev_dump'
|
||||
- 'for_each_netdev_feature'
|
||||
- 'for_each_netdev_in_bond_rcu'
|
||||
- 'for_each_netdev_rcu'
|
||||
- 'for_each_netdev_reverse'
|
||||
- 'for_each_netdev_safe'
|
||||
- 'for_each_new_connector_in_state'
|
||||
- 'for_each_new_crtc_in_state'
|
||||
- 'for_each_new_mst_mgr_in_state'
|
||||
- 'for_each_new_plane_in_state'
|
||||
- 'for_each_new_plane_in_state_reverse'
|
||||
- 'for_each_new_private_obj_in_state'
|
||||
- 'for_each_new_reg'
|
||||
- 'for_each_node'
|
||||
- 'for_each_node_by_name'
|
||||
- 'for_each_node_by_type'
|
||||
- 'for_each_node_mask'
|
||||
- 'for_each_node_state'
|
||||
- 'for_each_node_with_cpus'
|
||||
- 'for_each_node_with_property'
|
||||
- 'for_each_nonreserved_multicast_dest_pgid'
|
||||
- 'for_each_numa_hop_mask'
|
||||
- 'for_each_of_allnodes'
|
||||
- 'for_each_of_allnodes_from'
|
||||
- 'for_each_of_cpu_node'
|
||||
- 'for_each_of_pci_range'
|
||||
- 'for_each_old_connector_in_state'
|
||||
- 'for_each_old_crtc_in_state'
|
||||
- 'for_each_old_mst_mgr_in_state'
|
||||
- 'for_each_old_plane_in_state'
|
||||
- 'for_each_old_private_obj_in_state'
|
||||
- 'for_each_oldnew_connector_in_state'
|
||||
- 'for_each_oldnew_crtc_in_state'
|
||||
- 'for_each_oldnew_mst_mgr_in_state'
|
||||
- 'for_each_oldnew_plane_in_state'
|
||||
- 'for_each_oldnew_plane_in_state_reverse'
|
||||
- 'for_each_oldnew_private_obj_in_state'
|
||||
- 'for_each_online_cpu'
|
||||
- 'for_each_online_node'
|
||||
- 'for_each_online_pgdat'
|
||||
- 'for_each_or_bit'
|
||||
- 'for_each_path'
|
||||
- 'for_each_pci_bridge'
|
||||
- 'for_each_pci_dev'
|
||||
- 'for_each_pcm_streams'
|
||||
- 'for_each_physmem_range'
|
||||
- 'for_each_populated_zone'
|
||||
- 'for_each_possible_cpu'
|
||||
- 'for_each_present_blessed_reg'
|
||||
- 'for_each_present_cpu'
|
||||
- 'for_each_prime_number'
|
||||
- 'for_each_prime_number_from'
|
||||
- 'for_each_probe_cache_entry'
|
||||
- 'for_each_process'
|
||||
- 'for_each_process_thread'
|
||||
- 'for_each_prop_codec_conf'
|
||||
- 'for_each_prop_dai_codec'
|
||||
- 'for_each_prop_dai_cpu'
|
||||
- 'for_each_prop_dlc_codecs'
|
||||
- 'for_each_prop_dlc_cpus'
|
||||
- 'for_each_prop_dlc_platforms'
|
||||
- 'for_each_property_of_node'
|
||||
- 'for_each_reg'
|
||||
- 'for_each_reg_filtered'
|
||||
- 'for_each_reloc'
|
||||
- 'for_each_reloc_from'
|
||||
- 'for_each_requested_gpio'
|
||||
- 'for_each_requested_gpio_in_range'
|
||||
- 'for_each_reserved_mem_range'
|
||||
- 'for_each_reserved_mem_region'
|
||||
- 'for_each_rtd_codec_dais'
|
||||
- 'for_each_rtd_components'
|
||||
- 'for_each_rtd_cpu_dais'
|
||||
- 'for_each_rtd_dais'
|
||||
- 'for_each_sband_iftype_data'
|
||||
- 'for_each_script'
|
||||
- 'for_each_sec'
|
||||
- 'for_each_set_bit'
|
||||
- 'for_each_set_bit_from'
|
||||
- 'for_each_set_bit_wrap'
|
||||
- 'for_each_set_bitrange'
|
||||
- 'for_each_set_bitrange_from'
|
||||
- 'for_each_set_clump8'
|
||||
- 'for_each_sg'
|
||||
- 'for_each_sg_dma_page'
|
||||
- 'for_each_sg_page'
|
||||
- 'for_each_sgtable_dma_page'
|
||||
- 'for_each_sgtable_dma_sg'
|
||||
- 'for_each_sgtable_page'
|
||||
- 'for_each_sgtable_sg'
|
||||
- 'for_each_sibling_event'
|
||||
- 'for_each_sta_active_link'
|
||||
- 'for_each_subelement'
|
||||
- 'for_each_subelement_extid'
|
||||
- 'for_each_subelement_id'
|
||||
- 'for_each_sublist'
|
||||
- 'for_each_subsystem'
|
||||
- 'for_each_supported_activate_fn'
|
||||
- 'for_each_supported_inject_fn'
|
||||
- 'for_each_sym'
|
||||
- 'for_each_test'
|
||||
- 'for_each_thread'
|
||||
- 'for_each_token'
|
||||
- 'for_each_unicast_dest_pgid'
|
||||
- 'for_each_valid_link'
|
||||
- 'for_each_vif_active_link'
|
||||
- 'for_each_vma'
|
||||
- 'for_each_vma_range'
|
||||
- 'for_each_vsi'
|
||||
- 'for_each_wakeup_source'
|
||||
- 'for_each_zone'
|
||||
- 'for_each_zone_zonelist'
|
||||
- 'for_each_zone_zonelist_nodemask'
|
||||
- 'func_for_each_insn'
|
||||
- 'fwnode_for_each_available_child_node'
|
||||
- 'fwnode_for_each_child_node'
|
||||
- 'fwnode_for_each_parent_node'
|
||||
- 'fwnode_graph_for_each_endpoint'
|
||||
- 'gadget_for_each_ep'
|
||||
- 'genradix_for_each'
|
||||
- 'genradix_for_each_from'
|
||||
- 'genradix_for_each_reverse'
|
||||
- 'hash_for_each'
|
||||
- 'hash_for_each_possible'
|
||||
- 'hash_for_each_possible_rcu'
|
||||
- 'hash_for_each_possible_rcu_notrace'
|
||||
- 'hash_for_each_possible_safe'
|
||||
- 'hash_for_each_rcu'
|
||||
- 'hash_for_each_safe'
|
||||
- 'hashmap__for_each_entry'
|
||||
- 'hashmap__for_each_entry_safe'
|
||||
- 'hashmap__for_each_key_entry'
|
||||
- 'hashmap__for_each_key_entry_safe'
|
||||
- 'hctx_for_each_ctx'
|
||||
- 'hists__for_each_format'
|
||||
- 'hists__for_each_sort_list'
|
||||
- 'hlist_bl_for_each_entry'
|
||||
- 'hlist_bl_for_each_entry_rcu'
|
||||
- 'hlist_bl_for_each_entry_safe'
|
||||
- 'hlist_for_each'
|
||||
- 'hlist_for_each_entry'
|
||||
- 'hlist_for_each_entry_continue'
|
||||
- 'hlist_for_each_entry_continue_rcu'
|
||||
- 'hlist_for_each_entry_continue_rcu_bh'
|
||||
- 'hlist_for_each_entry_from'
|
||||
- 'hlist_for_each_entry_from_rcu'
|
||||
- 'hlist_for_each_entry_rcu'
|
||||
- 'hlist_for_each_entry_rcu_bh'
|
||||
- 'hlist_for_each_entry_rcu_notrace'
|
||||
- 'hlist_for_each_entry_safe'
|
||||
- 'hlist_for_each_entry_srcu'
|
||||
- 'hlist_for_each_safe'
|
||||
- 'hlist_nulls_for_each_entry'
|
||||
- 'hlist_nulls_for_each_entry_from'
|
||||
- 'hlist_nulls_for_each_entry_rcu'
|
||||
- 'hlist_nulls_for_each_entry_safe'
|
||||
- 'i3c_bus_for_each_i2cdev'
|
||||
- 'i3c_bus_for_each_i3cdev'
|
||||
- 'idr_for_each_entry'
|
||||
- 'idr_for_each_entry_continue'
|
||||
- 'idr_for_each_entry_continue_ul'
|
||||
- 'idr_for_each_entry_ul'
|
||||
- 'in_dev_for_each_ifa_rcu'
|
||||
- 'in_dev_for_each_ifa_rtnl'
|
||||
- 'inet_bind_bucket_for_each'
|
||||
- 'interval_tree_for_each_span'
|
||||
- 'intlist__for_each_entry'
|
||||
- 'intlist__for_each_entry_safe'
|
||||
- 'kcore_copy__for_each_phdr'
|
||||
- 'key_for_each'
|
||||
- 'key_for_each_safe'
|
||||
- 'klp_for_each_func'
|
||||
- 'klp_for_each_func_safe'
|
||||
- 'klp_for_each_func_static'
|
||||
- 'klp_for_each_object'
|
||||
- 'klp_for_each_object_safe'
|
||||
- 'klp_for_each_object_static'
|
||||
- 'kunit_suite_for_each_test_case'
|
||||
- 'kvm_for_each_memslot'
|
||||
- 'kvm_for_each_memslot_in_gfn_range'
|
||||
- 'kvm_for_each_vcpu'
|
||||
- 'libbpf_nla_for_each_attr'
|
||||
- 'list_for_each'
|
||||
- 'list_for_each_codec'
|
||||
- 'list_for_each_codec_safe'
|
||||
- 'list_for_each_continue'
|
||||
- 'list_for_each_entry'
|
||||
- 'list_for_each_entry_continue'
|
||||
- 'list_for_each_entry_continue_rcu'
|
||||
- 'list_for_each_entry_continue_reverse'
|
||||
- 'list_for_each_entry_from'
|
||||
- 'list_for_each_entry_from_rcu'
|
||||
- 'list_for_each_entry_from_reverse'
|
||||
- 'list_for_each_entry_lockless'
|
||||
- 'list_for_each_entry_rcu'
|
||||
- 'list_for_each_entry_reverse'
|
||||
- 'list_for_each_entry_safe'
|
||||
- 'list_for_each_entry_safe_continue'
|
||||
- 'list_for_each_entry_safe_from'
|
||||
- 'list_for_each_entry_safe_reverse'
|
||||
- 'list_for_each_entry_srcu'
|
||||
- 'list_for_each_from'
|
||||
- 'list_for_each_prev'
|
||||
- 'list_for_each_prev_safe'
|
||||
- 'list_for_each_rcu'
|
||||
- 'list_for_each_reverse'
|
||||
- 'list_for_each_safe'
|
||||
- 'llist_for_each'
|
||||
- 'llist_for_each_entry'
|
||||
- 'llist_for_each_entry_safe'
|
||||
- 'llist_for_each_safe'
|
||||
- 'lwq_for_each_safe'
|
||||
- 'map__for_each_symbol'
|
||||
- 'map__for_each_symbol_by_name'
|
||||
- 'maps__for_each_entry'
|
||||
- 'maps__for_each_entry_safe'
|
||||
- 'mas_for_each'
|
||||
- 'mci_for_each_dimm'
|
||||
- 'media_device_for_each_entity'
|
||||
- 'media_device_for_each_intf'
|
||||
- 'media_device_for_each_link'
|
||||
- 'media_device_for_each_pad'
|
||||
- 'media_entity_for_each_pad'
|
||||
- 'media_pipeline_for_each_entity'
|
||||
- 'media_pipeline_for_each_pad'
|
||||
- 'mlx5_lag_for_each_peer_mdev'
|
||||
- 'msi_domain_for_each_desc'
|
||||
- 'msi_for_each_desc'
|
||||
- 'mt_for_each'
|
||||
- 'nanddev_io_for_each_page'
|
||||
- 'netdev_for_each_lower_dev'
|
||||
- 'netdev_for_each_lower_private'
|
||||
- 'netdev_for_each_lower_private_rcu'
|
||||
- 'netdev_for_each_mc_addr'
|
||||
- 'netdev_for_each_synced_mc_addr'
|
||||
- 'netdev_for_each_synced_uc_addr'
|
||||
- 'netdev_for_each_uc_addr'
|
||||
- 'netdev_for_each_upper_dev_rcu'
|
||||
- 'netdev_hw_addr_list_for_each'
|
||||
- 'nft_rule_for_each_expr'
|
||||
- 'nla_for_each_attr'
|
||||
- 'nla_for_each_nested'
|
||||
- 'nlmsg_for_each_attr'
|
||||
- 'nlmsg_for_each_msg'
|
||||
- 'nr_neigh_for_each'
|
||||
- 'nr_neigh_for_each_safe'
|
||||
- 'nr_node_for_each'
|
||||
- 'nr_node_for_each_safe'
|
||||
- 'of_for_each_phandle'
|
||||
- 'of_property_for_each_string'
|
||||
- 'of_property_for_each_u32'
|
||||
- 'pci_bus_for_each_resource'
|
||||
- 'pci_dev_for_each_resource'
|
||||
- 'pcl_for_each_chunk'
|
||||
- 'pcl_for_each_segment'
|
||||
- 'pcm_for_each_format'
|
||||
- 'perf_config_items__for_each_entry'
|
||||
- 'perf_config_sections__for_each_entry'
|
||||
- 'perf_config_set__for_each_entry'
|
||||
- 'perf_cpu_map__for_each_cpu'
|
||||
- 'perf_cpu_map__for_each_idx'
|
||||
- 'perf_evlist__for_each_entry'
|
||||
- 'perf_evlist__for_each_entry_reverse'
|
||||
- 'perf_evlist__for_each_entry_safe'
|
||||
- 'perf_evlist__for_each_evsel'
|
||||
- 'perf_evlist__for_each_mmap'
|
||||
- 'perf_hpp_list__for_each_format'
|
||||
- 'perf_hpp_list__for_each_format_safe'
|
||||
- 'perf_hpp_list__for_each_sort_list'
|
||||
- 'perf_hpp_list__for_each_sort_list_safe'
|
||||
- 'perf_tool_event__for_each_event'
|
||||
- 'plist_for_each'
|
||||
- 'plist_for_each_continue'
|
||||
- 'plist_for_each_entry'
|
||||
- 'plist_for_each_entry_continue'
|
||||
- 'plist_for_each_entry_safe'
|
||||
- 'plist_for_each_safe'
|
||||
- 'pnp_for_each_card'
|
||||
- 'pnp_for_each_dev'
|
||||
- 'protocol_for_each_card'
|
||||
- 'protocol_for_each_dev'
|
||||
- 'queue_for_each_hw_ctx'
|
||||
- 'radix_tree_for_each_slot'
|
||||
- 'radix_tree_for_each_tagged'
|
||||
- 'rb_for_each'
|
||||
- 'rbtree_postorder_for_each_entry_safe'
|
||||
- 'rdma_for_each_block'
|
||||
- 'rdma_for_each_port'
|
||||
- 'rdma_umem_for_each_dma_block'
|
||||
- 'resort_rb__for_each_entry'
|
||||
- 'resource_list_for_each_entry'
|
||||
- 'resource_list_for_each_entry_safe'
|
||||
- 'rhl_for_each_entry_rcu'
|
||||
- 'rhl_for_each_rcu'
|
||||
- 'rht_for_each'
|
||||
- 'rht_for_each_entry'
|
||||
- 'rht_for_each_entry_from'
|
||||
- 'rht_for_each_entry_rcu'
|
||||
- 'rht_for_each_entry_rcu_from'
|
||||
- 'rht_for_each_entry_safe'
|
||||
- 'rht_for_each_from'
|
||||
- 'rht_for_each_rcu'
|
||||
- 'rht_for_each_rcu_from'
|
||||
- 'rq_for_each_bvec'
|
||||
- 'rq_for_each_segment'
|
||||
- 'rq_list_for_each'
|
||||
- 'rq_list_for_each_safe'
|
||||
- 'sample_read_group__for_each'
|
||||
- 'scsi_for_each_prot_sg'
|
||||
- 'scsi_for_each_sg'
|
||||
- 'sctp_for_each_hentry'
|
||||
- 'sctp_skb_for_each'
|
||||
- 'sec_for_each_insn'
|
||||
- 'sec_for_each_insn_continue'
|
||||
- 'sec_for_each_insn_from'
|
||||
- 'sec_for_each_sym'
|
||||
- 'shdma_for_each_chan'
|
||||
- 'shost_for_each_device'
|
||||
- 'sk_for_each'
|
||||
- 'sk_for_each_bound'
|
||||
- 'sk_for_each_bound_bhash2'
|
||||
- 'sk_for_each_entry_offset_rcu'
|
||||
- 'sk_for_each_from'
|
||||
- 'sk_for_each_rcu'
|
||||
- 'sk_for_each_safe'
|
||||
- 'sk_nulls_for_each'
|
||||
- 'sk_nulls_for_each_from'
|
||||
- 'sk_nulls_for_each_rcu'
|
||||
- 'snd_array_for_each'
|
||||
- 'snd_pcm_group_for_each_entry'
|
||||
- 'snd_soc_dapm_widget_for_each_path'
|
||||
- 'snd_soc_dapm_widget_for_each_path_safe'
|
||||
- 'snd_soc_dapm_widget_for_each_sink_path'
|
||||
- 'snd_soc_dapm_widget_for_each_source_path'
|
||||
- 'strlist__for_each_entry'
|
||||
- 'strlist__for_each_entry_safe'
|
||||
- 'sym_for_each_insn'
|
||||
- 'sym_for_each_insn_continue_reverse'
|
||||
- 'symbols__for_each_entry'
|
||||
- 'tb_property_for_each'
|
||||
- 'tcf_act_for_each_action'
|
||||
- 'tcf_exts_for_each_action'
|
||||
- 'ttm_resource_manager_for_each_res'
|
||||
- 'twsk_for_each_bound_bhash2'
|
||||
- 'udp_portaddr_for_each_entry'
|
||||
- 'udp_portaddr_for_each_entry_rcu'
|
||||
- 'usb_hub_for_each_child'
|
||||
- 'v4l2_device_for_each_subdev'
|
||||
- 'v4l2_m2m_for_each_dst_buf'
|
||||
- 'v4l2_m2m_for_each_dst_buf_safe'
|
||||
- 'v4l2_m2m_for_each_src_buf'
|
||||
- 'v4l2_m2m_for_each_src_buf_safe'
|
||||
- 'virtio_device_for_each_vq'
|
||||
- 'while_for_each_ftrace_op'
|
||||
- 'xa_for_each'
|
||||
- 'xa_for_each_marked'
|
||||
- 'xa_for_each_range'
|
||||
- 'xa_for_each_start'
|
||||
- 'xas_for_each'
|
||||
- 'xas_for_each_conflict'
|
||||
- 'xas_for_each_marked'
|
||||
- 'xbc_array_for_each_value'
|
||||
- 'xbc_for_each_key_value'
|
||||
- 'xbc_node_for_each_array_value'
|
||||
- 'xbc_node_for_each_child'
|
||||
- 'xbc_node_for_each_key_value'
|
||||
- 'xbc_node_for_each_subkey'
|
||||
- 'zorro_for_each_dev'
|
||||
|
||||
IncludeBlocks: Preserve
|
||||
IncludeCategories:
|
||||
- Regex: '.*'
|
||||
Priority: 1
|
||||
IncludeIsMainRegex: '(Test)?$'
|
||||
IndentCaseLabels: false
|
||||
IndentGotoLabels: false
|
||||
IndentPPDirectives: None
|
||||
IndentWidth: 8
|
||||
IndentAccessModifiers: false
|
||||
IndentWrappedFunctionNames: false
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCBinPackProtocolList: Auto
|
||||
ObjCBlockIndentWidth: 8
|
||||
ObjCSpaceAfterProperty: true
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
|
||||
# Taken from git's rules
|
||||
PenaltyBreakAssignment: 10
|
||||
PenaltyBreakBeforeFirstCallParameter: 30
|
||||
PenaltyBreakComment: 10
|
||||
PenaltyBreakFirstLessLess: 0
|
||||
PenaltyBreakString: 10
|
||||
PenaltyExcessCharacter: 100
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
|
||||
PointerAlignment: Right
|
||||
ReflowComments: false
|
||||
SortIncludes: false
|
||||
SortUsingDeclarations: false
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeParens: ControlStatementsExceptForEachMacros
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: false
|
||||
SpacesInContainerLiterals: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Cpp03
|
||||
TabWidth: 8
|
||||
UseTab: Always
|
||||
...
|
||||
4
.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
build/*
|
||||
build-vscode/*
|
||||
characters/*
|
||||
resources/buildings/*
|
||||
7
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"cmake.generator": "Unix Makefiles",
|
||||
"cmake.configureSettings": {
|
||||
"CMAKE_PREFIX_PATH": "/media/slapin/library/ogre/ogre-sdk"
|
||||
},
|
||||
"cmake.buildDirectory": "${workspaceFolder}/build-vscode"
|
||||
}
|
||||
62
.vscode/tasks.json
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"type": "cmake",
|
||||
"label": "CMake: configure",
|
||||
"command": "configure",
|
||||
"problemMatcher": [],
|
||||
"detail": "CMake config"
|
||||
},
|
||||
{
|
||||
"type": "cmake",
|
||||
"label": "CMake: clean rebuild",
|
||||
"command": "build",
|
||||
"targets": [
|
||||
"GuiTest",
|
||||
"0_Bootstrap",
|
||||
"TerrainTest",
|
||||
"Procedural"
|
||||
],
|
||||
"group": "build",
|
||||
"problemMatcher": [],
|
||||
"detail": "CMake clean rebuild task"
|
||||
},
|
||||
{
|
||||
"type": "cmake",
|
||||
"label": "CMake: clean rebuild",
|
||||
"command": "cleanRebuild",
|
||||
"targets": [
|
||||
"GuiTest",
|
||||
"0_Bootstrap",
|
||||
"TerrainTest",
|
||||
"Procedural"
|
||||
],
|
||||
"group": "build",
|
||||
"problemMatcher": [],
|
||||
"detail": "CMake clean rebuild task"
|
||||
},
|
||||
{
|
||||
"type": "cmake",
|
||||
"label": "CMake: complete build",
|
||||
"command": "build",
|
||||
"targets": [
|
||||
"all"
|
||||
],
|
||||
"group": "build",
|
||||
"problemMatcher": [],
|
||||
"detail": "CMake build"
|
||||
},
|
||||
{
|
||||
"type": "cmake",
|
||||
"label": "CMake: complete rebuild",
|
||||
"command": "cleanRebuild",
|
||||
"targets": [
|
||||
"all"
|
||||
],
|
||||
"group": "build",
|
||||
"problemMatcher": [],
|
||||
"detail": "CMake clean rebuild task"
|
||||
}
|
||||
]
|
||||
}
|
||||
807
Bootstrap.cpp
@@ -2,19 +2,778 @@
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at https://www.ogre3d.org/licensing.
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
#include <iostream>
|
||||
|
||||
#include "Ogre.h"
|
||||
#include "OgreApplicationContext.h"
|
||||
#include "Bullet/OgreBullet.h"
|
||||
#include "BulletCollision/CollisionDispatch/btGhostObject.h"
|
||||
#include "btKinematicCharacterController.h"
|
||||
#include "LinearMath/btTransform.h"
|
||||
#include "OgrePageManager.h"
|
||||
|
||||
class CharacterController {
|
||||
#define CAM_HEIGHT 1.6f // height of camera above character's center of mass
|
||||
#define RUN_SPEED 17 // character running speed in units per second
|
||||
#define TURN_SPEED 500.0f // character turning in degrees per second
|
||||
#define ANIM_FADE_SPEED 7.5f // animation crossfade speed in % of full weight per second
|
||||
using Real = Ogre::Real;
|
||||
using Math = Ogre::Math;
|
||||
|
||||
class WorldData {
|
||||
std::unique_ptr<Ogre::Bullet::DynamicsWorld> mDynWorld;
|
||||
std::unique_ptr<Ogre::Bullet::DebugDrawer> mDbgDraw;
|
||||
std::unique_ptr<Ogre::Root> mRoot;
|
||||
std::unique_ptr<Ogre::SceneManager> mScnMgr;
|
||||
std::unique_ptr<btDynamicsWorld> mbtWorld;
|
||||
std::unique_ptr<Ogre::PageManager> mPageManager;
|
||||
Ogre::PagedWorld *mPagedWorld;
|
||||
private:
|
||||
static WorldData *singleton;
|
||||
class DummyPageProvider : public Ogre::PageProvider
|
||||
{
|
||||
public:
|
||||
bool prepareProceduralPage(Ogre::Page* page, Ogre::PagedWorldSection* section) override { return true; }
|
||||
bool loadProceduralPage(Ogre::Page* page, Ogre::PagedWorldSection* section) override { return true; }
|
||||
bool unloadProceduralPage(Ogre::Page* page, Ogre::PagedWorldSection* section) override { return true; }
|
||||
bool unprepareProceduralPage(Ogre::Page* page, Ogre::PagedWorldSection* section) override { return true; }
|
||||
};
|
||||
DummyPageProvider mDummyPageProvider;
|
||||
|
||||
WorldData(Ogre::Root *root, Ogre::SceneManager *scnMgr)
|
||||
: mDynWorld(new Ogre::Bullet::DynamicsWorld(Ogre::Vector3(0, -9.8, 0)))
|
||||
, mDbgDraw(new Ogre::Bullet::DebugDrawer(scnMgr->getRootSceneNode(), mDynWorld->getBtWorld()))
|
||||
, mRoot(root)
|
||||
, mScnMgr(scnMgr)
|
||||
, mbtWorld(mDynWorld->getBtWorld())
|
||||
, mPageManager(nullptr)
|
||||
, mPagedWorld(nullptr)
|
||||
{
|
||||
}
|
||||
public:
|
||||
static void init(Ogre::Root *root, Ogre::SceneManager *scnMgr)
|
||||
{
|
||||
singleton = new WorldData(root, scnMgr);
|
||||
}
|
||||
static WorldData *get_singleton()
|
||||
{
|
||||
return singleton;
|
||||
}
|
||||
static void cleanup()
|
||||
{
|
||||
if (singleton)
|
||||
delete singleton;
|
||||
singleton = nullptr;
|
||||
}
|
||||
Ogre::SceneManager *getSceneManager()
|
||||
{
|
||||
return mScnMgr.get();
|
||||
}
|
||||
Ogre::Root *getRoot()
|
||||
{
|
||||
return mRoot.get();
|
||||
}
|
||||
void createTrimesh(Ogre::Entity *entity)
|
||||
{
|
||||
}
|
||||
btPairCachingGhostObject *addGhostObject(Ogre::Entity *ent, btCollisionShape *shape, int group = 1, int mask = 0xFFFF)
|
||||
{
|
||||
btDynamicsWorld *world = mDynWorld->getBtWorld();
|
||||
Ogre::SceneNode *node = ent->getParentSceneNode();
|
||||
btPairCachingGhostObject *ghost = new btPairCachingGhostObject();
|
||||
ghost->setCollisionShape(shape);
|
||||
ghost->setCollisionFlags(ghost->getCollisionFlags()
|
||||
| btCollisionObject::CF_NO_CONTACT_RESPONSE
|
||||
| btCollisionObject::CF_CHARACTER_OBJECT
|
||||
);
|
||||
getWorld()->attachCollisionObject(ghost, ent, group, mask);
|
||||
#if 0
|
||||
getBtWorld()
|
||||
->getBroadphase()->getOverlappingPairCache()
|
||||
->setInternalGhostPairCallback(new btGhostPairCallback());
|
||||
ghost->setUserPointer(new EntityCollisionListener{ent, nullptr});
|
||||
#endif
|
||||
return ghost;
|
||||
|
||||
}
|
||||
btRigidBody *addRigidBody(float mass, Ogre::Entity *ent, Ogre::Bullet::ColliderType ct, int group = 1, int mask = 0xFFFF)
|
||||
{
|
||||
btDynamicsWorld *world = mDynWorld->getBtWorld();
|
||||
Ogre::SceneNode *node = ent->getParentSceneNode();
|
||||
Ogre::Bullet::RigidBodyState *state = new Ogre::Bullet::RigidBodyState(node);
|
||||
btCollisionShape *cs;
|
||||
btCollisionShape *shape;
|
||||
btVector3 inertia(0, 0, 0);
|
||||
switch(ct) {
|
||||
case Ogre::Bullet::CT_TRIMESH: {
|
||||
cs = Ogre::Bullet::createTrimeshCollider(ent);
|
||||
if (mass != 0)
|
||||
cs->calculateLocalInertia(mass, inertia);
|
||||
} break;
|
||||
case Ogre::Bullet::CT_CAPSULE: {
|
||||
cs = new btCompoundShape();
|
||||
btScalar height = 1.0f;
|
||||
btScalar radius = 0.3f;
|
||||
shape = new btCapsuleShape(radius, 2 * height - 2 * radius);
|
||||
btTransform transform;
|
||||
transform.setIdentity();
|
||||
transform.setOrigin(btVector3(0, 1, 0));
|
||||
static_cast<btCompoundShape *>(cs)->addChildShape(transform, shape);
|
||||
btScalar masses[1] = {mass};
|
||||
btTransform principal;
|
||||
static_cast<btCompoundShape *>(cs)->calculatePrincipalAxisTransform(masses, principal, inertia);
|
||||
} break;
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
btRigidBody *body = new btRigidBody(mass, state, cs, inertia);
|
||||
getWorld()->attachRigidBody(body, ent, nullptr, group, mask);
|
||||
#if 0
|
||||
body->setUserPointer(new EntityCollisionListener{ent, nullptr});
|
||||
// btRigidBody *body = mDynWorld->addRigidBody(0, ent, Ogre::Bullet::CT_TRIMESH);
|
||||
#endif
|
||||
return body;
|
||||
}
|
||||
btRigidBody *addKinematicRigidBody(float mass, Ogre::Entity *ent, Ogre::Bullet::ColliderType ct, int group = 1, int mask = 0xFFFF)
|
||||
{
|
||||
return mDynWorld->addKinematicRigidBody(ent, ct, group, mask);
|
||||
}
|
||||
btDynamicsWorld *getBtWorld()
|
||||
{
|
||||
return mDynWorld->getBtWorld();
|
||||
}
|
||||
Ogre::Bullet::DynamicsWorld *getWorld()
|
||||
{
|
||||
return mDynWorld.get();
|
||||
}
|
||||
void update(float delta)
|
||||
{
|
||||
WorldData::get_singleton()
|
||||
->getBtWorld()->stepSimulation(delta, 10);
|
||||
mDbgDraw->update();
|
||||
}
|
||||
void initPagedWorld(Ogre::Camera *camera)
|
||||
{
|
||||
mPageManager = std::make_unique<Ogre::PageManager>();
|
||||
mPageManager->setPageProvider(&mDummyPageProvider);
|
||||
mPageManager->addCamera(camera);
|
||||
mPageManager->setDebugDisplayLevel(0);
|
||||
mPagedWorld = mPageManager->createWorld();
|
||||
}
|
||||
};
|
||||
WorldData *WorldData::singleton = nullptr;
|
||||
|
||||
class MainWorld : public Ogre::FrameListener
|
||||
{
|
||||
btRigidBody *mFloorBody;
|
||||
public:
|
||||
void setup()
|
||||
{
|
||||
// mScnMgr = scnMgr;
|
||||
// mDynWorld.reset(new Ogre::Bullet::DynamicsWorld(Ogre::Vector3(0, -9.8, 0)));
|
||||
// mDbgDraw.reset(new Ogre::Bullet::DebugDrawer(mScnMgr->getRootSceneNode(), mDynWorld->getBtWorld()));
|
||||
Ogre::MeshManager::getSingleton().createPlane("floor", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||
Ogre::Plane(Ogre::Vector3::UNIT_Y, 0), 100, 100, 10, 10, true, 1, 10, 10, Ogre::Vector3::UNIT_Z);
|
||||
|
||||
// create a floor entity, give it a material, and place it at the origin
|
||||
Ogre::SceneManager *scnMgr = WorldData::get_singleton()->getSceneManager();
|
||||
Ogre::Entity *floor = scnMgr->createEntity("Floor", "floor");
|
||||
scnMgr->getRootSceneNode()->attachObject(floor);
|
||||
mFloorBody = WorldData::get_singleton()->addRigidBody(0, floor, Ogre::Bullet::CT_TRIMESH);
|
||||
}
|
||||
btRigidBody *addCharacter(Ogre::Entity *ent, float mass)
|
||||
{
|
||||
return WorldData::get_singleton()->addKinematicRigidBody(mass, ent, Ogre::Bullet::CT_COMPOUND);
|
||||
}
|
||||
bool frameStarted(const Ogre::FrameEvent& evt) override;
|
||||
};
|
||||
class CharacterController : public OgreBites::InputListener, Ogre::FrameListener {
|
||||
enum AnimID
|
||||
{
|
||||
ANIM_IDLE = 0,
|
||||
ANIM_WALK,
|
||||
ANIM_RUN,
|
||||
NUM_ANIMS,
|
||||
ANIM_NONE = NUM_ANIMS
|
||||
};
|
||||
Ogre::Node *mRootBone;
|
||||
Ogre::SceneNode *mCameraNode;
|
||||
Ogre::Camera *mCamera;
|
||||
Ogre::SceneManager *mScnMgr;
|
||||
|
||||
Ogre::SceneNode *mCameraPivot;
|
||||
Ogre::SceneNode *mCameraGoal, *mBodyNode;
|
||||
Ogre::Entity *mBodyEnt;
|
||||
Real mPivotPitch;
|
||||
Real mVerticalVelocity;
|
||||
Ogre::Vector3 mKeyDirection; // player's local intended direction based on WASD keys
|
||||
Ogre::Vector3 mGoalDirection; // actual intended direction in world-space
|
||||
Ogre::AnimationState *mAnims[NUM_ANIMS]; // master animation list
|
||||
Ogre::Animation *mSkelAnimations[NUM_ANIMS];
|
||||
Ogre::NodeAnimationTrack *mHipsTracks[NUM_ANIMS];
|
||||
Ogre::NodeAnimationTrack *mRootTracks[NUM_ANIMS];
|
||||
AnimID mAnimID;
|
||||
bool mFadingIn[NUM_ANIMS]; // which animations are fading in
|
||||
bool mFadingOut[NUM_ANIMS]; // which animations are fading out
|
||||
Real mTimer; // general timer to see how long animations have been playing
|
||||
Ogre::Skeleton *mSkeleton;
|
||||
bool mRunning;
|
||||
MainWorld *world;
|
||||
Ogre::Vector3 rootMotion;
|
||||
Ogre::Quaternion rootRotation;
|
||||
// btRigidBody *mRigidBody;
|
||||
btCompoundShape *mCollisionShape;
|
||||
btPairCachingGhostObject *mGhostObject;
|
||||
btKinematicCharacterController *mController;
|
||||
public:
|
||||
CharacterController(Ogre::SceneNode *camNode, Ogre::Camera *cam, Ogre::SceneManager *scnMgr, MainWorld *world);
|
||||
~CharacterController();
|
||||
private:
|
||||
void setupBody();
|
||||
void setupCamera();
|
||||
void setupAnimations();
|
||||
public:
|
||||
bool keyPressed(const OgreBites::KeyboardEvent& evt) override;
|
||||
bool keyReleased(const OgreBites::KeyboardEvent& evt) override;
|
||||
bool mouseMoved(const OgreBites::MouseMotionEvent& evt) override;
|
||||
bool mouseWheelRolled(const OgreBites::MouseWheelEvent& evt) override;
|
||||
bool mousePressed(const OgreBites::MouseButtonEvent& evt) override;
|
||||
bool frameStarted(const Ogre::FrameEvent& evt) override;
|
||||
void frameRendered(const Ogre::FrameEvent& evt) override;
|
||||
private:
|
||||
void updateBody(Ogre::Real deltaTime);
|
||||
void updateAnimations(Real deltaTime);
|
||||
void updateRootMotion(Real deltaTime);
|
||||
void fadeAnimations(Real deltaTime);
|
||||
void updateCamera(Real deltaTime);
|
||||
void updateCameraGoal(Real deltaYaw, Real deltaPitch, Real deltaZoom);
|
||||
void setAnimation(AnimID id, bool reset = false);
|
||||
#if 0
|
||||
struct testMotionResult {
|
||||
};
|
||||
struct recoverResult {
|
||||
};
|
||||
|
||||
bool bodyTestMotion(btRigidBody *body,
|
||||
const btTransform &from,
|
||||
const btVector3 &motion, bool infinite_inertia,
|
||||
textMotionResult *result,
|
||||
bool excludeRaycastShapes,
|
||||
const std::set<btCollisionObject *> &exclude);
|
||||
bool recoverFromPenetration(btRigidBody *body,
|
||||
const btTransform &body_position,
|
||||
btScalar recover_movement_scale,
|
||||
bool infinite_inertia,
|
||||
btVector3 &delta_recover_movement,
|
||||
recoverResult *recover_result,
|
||||
const std::set<btCollisionObject *> &exclude);
|
||||
#endif
|
||||
inline btQuaternion convert(const Ogre::Quaternion& q)
|
||||
{
|
||||
return btQuaternion(q.x, q.y, q.z, q.w);
|
||||
}
|
||||
inline btVector3 convert(const Ogre::Vector3& v)
|
||||
{
|
||||
return btVector3(v.x, v.y, v.z);
|
||||
}
|
||||
inline btTransform convert(const Ogre::Quaternion& q, const Ogre::Vector3& v)
|
||||
{
|
||||
btQuaternion mq = convert(q);
|
||||
btVector3 mv = convert(v);
|
||||
return btTransform(mq, mv);
|
||||
}
|
||||
inline Ogre::Quaternion convert(const btQuaternion& q)
|
||||
{
|
||||
return Ogre::Quaternion(q.w(), q.x(), q.y(), q.z());
|
||||
}
|
||||
inline Ogre::Vector3 convert(const btVector3& v)
|
||||
{
|
||||
return Ogre::Vector3(v.x(), v.y(), v.z());
|
||||
}
|
||||
inline void convert(const btTransform &from, Ogre::Quaternion &q, Ogre::Vector3 &v)
|
||||
{
|
||||
q = convert(from.getRotation());
|
||||
v = convert(from.getOrigin());
|
||||
}
|
||||
};
|
||||
CharacterController::CharacterController(
|
||||
Ogre::SceneNode *camNode,
|
||||
Ogre::Camera *cam,
|
||||
Ogre::SceneManager *scnMgr,
|
||||
MainWorld *world)
|
||||
: mCameraNode(camNode)
|
||||
, mCamera(cam)
|
||||
, mScnMgr(scnMgr)
|
||||
, mPivotPitch(0)
|
||||
, mVerticalVelocity(0)
|
||||
, mAnimID(ANIM_NONE)
|
||||
, mRunning(false)
|
||||
, world(world)
|
||||
, mCollisionShape(nullptr)
|
||||
, mGhostObject(nullptr)
|
||||
, mController(nullptr)
|
||||
{
|
||||
|
||||
setupBody();
|
||||
setupCamera();
|
||||
setupAnimations();
|
||||
}
|
||||
CharacterController::~CharacterController()
|
||||
{
|
||||
}
|
||||
void CharacterController::setupBody()
|
||||
{
|
||||
mBodyEnt = mScnMgr->createEntity("normal-male.glb");
|
||||
mBodyNode = mScnMgr->getRootSceneNode()->createChildSceneNode();
|
||||
mBodyNode->attachObject(mBodyEnt);
|
||||
mSkeleton = mBodyEnt->getSkeleton();
|
||||
// mRigidBody = world->addCharacter(mBodyEnt, 0);
|
||||
// mCollisionShape = static_cast<btCompoundShape *>(mRigidBody->getCollisionShape());
|
||||
mGhostObject = new btPairCachingGhostObject();
|
||||
mCollisionShape = new btCompoundShape;
|
||||
mGhostObject->setCollisionShape(mCollisionShape);
|
||||
|
||||
{
|
||||
btVector3 inertia(0, 0, 0);
|
||||
// mCollisionShape = new btCompoundShape();
|
||||
btScalar height = 1.0f;
|
||||
btScalar radius = 0.3f;
|
||||
btCapsuleShape *shape = new btCapsuleShape(radius, 2 * height - 2 * radius);
|
||||
btTransform transform;
|
||||
transform.setIdentity();
|
||||
transform.setOrigin(btVector3(0, 1, 0));
|
||||
static_cast<btCompoundShape *>(mCollisionShape)->addChildShape(transform, shape);
|
||||
btScalar masses[1] = {0};
|
||||
btTransform principal;
|
||||
static_cast<btCompoundShape *>(mCollisionShape)->calculatePrincipalAxisTransform(masses, principal, inertia);
|
||||
}
|
||||
mGhostObject->setCollisionFlags(btCollisionObject::CF_KINEMATIC_OBJECT | btCollisionObject::CF_NO_CONTACT_RESPONSE);
|
||||
mGhostObject->setActivationState(DISABLE_DEACTIVATION);
|
||||
Ogre::Bullet::KinematicMotionSimple *controller = new Ogre::Bullet::KinematicMotionSimple(mGhostObject, mBodyNode);
|
||||
WorldData::get_singleton()->getWorld()->attachCollisionObject(mGhostObject, mBodyEnt, btBroadphaseProxy::AllFilter, btBroadphaseProxy::AllFilter);
|
||||
WorldData::get_singleton()->getBtWorld()->addAction(controller);
|
||||
|
||||
assert(mCollisionShape);
|
||||
#if 0
|
||||
if (mRigidBody->getMass() == 0) {
|
||||
#if 0
|
||||
mRigidBody->setCollisionFlags(mRigidBody->getCollisionFlags()
|
||||
| btCollisionObject::CF_KINEMATIC_OBJECT
|
||||
| btCollisionObject::CF_NO_CONTACT_RESPONSE
|
||||
);
|
||||
#endif
|
||||
#if 0
|
||||
mGhostObject->setWorldTransform(mRigidBody->getWorldTransform());
|
||||
WorldData::get_singleton()->getBtWorld()
|
||||
->getBroadphase()->getOverlappingPairCache()
|
||||
->setInternalGhostPairCallback(new btGhostPairCallback());
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
mRigidBody->setActivationState(DISABLE_DEACTIVATION);
|
||||
#endif
|
||||
#if 0
|
||||
{
|
||||
Ogre::Entity *e2 = mScnMgr->createEntity("normal-male.glb");
|
||||
Ogre::SceneNode *e2node = mScnMgr->getRootSceneNode()->createChildSceneNode();
|
||||
e2node->attachObject(e2);
|
||||
mGhostObject = WorldData::get_singleton()->addGhostObject(e2, mCollisionShape);
|
||||
mController = new btKinematicCharacterController(mGhostObject, mCollisionShape, 0.5f);
|
||||
WorldData::get_singleton()->getBtWorld()->addAction(mController);
|
||||
}
|
||||
#endif
|
||||
assert(mSkeleton->hasBone("Root"));
|
||||
mRootBone = mSkeleton->getBone("Root");
|
||||
assert(mRootBone);
|
||||
}
|
||||
void CharacterController::setupCamera()
|
||||
{
|
||||
// create a pivot at roughly the character's shoulder
|
||||
mCameraPivot = mScnMgr->getRootSceneNode()->createChildSceneNode();
|
||||
mCameraGoal = mCameraPivot->createChildSceneNode(Ogre::Vector3(0, 2, 3));
|
||||
mCameraNode->setPosition(mCameraPivot->getPosition() + mCameraGoal->getPosition());
|
||||
mCameraPivot->setFixedYawAxis(true);
|
||||
mCameraGoal->setFixedYawAxis(true);
|
||||
mCameraNode->setFixedYawAxis(true);
|
||||
// our model is quite small, so reduce the clipping planes
|
||||
mCamera->setNearClipDistance(0.1f);
|
||||
mCamera->setFarClipDistance(700);
|
||||
|
||||
mPivotPitch = 0;
|
||||
mKeyDirection = Ogre::Vector3::ZERO;
|
||||
mVerticalVelocity = 0;
|
||||
}
|
||||
void CharacterController::setupAnimations()
|
||||
{
|
||||
int i, j;
|
||||
mSkeleton->setBlendMode(Ogre::ANIMBLEND_CUMULATIVE);
|
||||
Ogre::String animNames[NUM_ANIMS] = {"idle", "walking", "running"};
|
||||
for (i = 0; i < NUM_ANIMS; i++) {
|
||||
mAnims[i] = mBodyEnt->getAnimationState(animNames[i]);
|
||||
mAnims[i]->setLoop(true);
|
||||
mAnims[i]->setEnabled(true);
|
||||
mAnims[i]->setWeight(0);
|
||||
mFadingIn[i] = false;
|
||||
mFadingOut[i] = false;
|
||||
mSkelAnimations[i] = mSkeleton->getAnimation(animNames[i]);
|
||||
for (const auto& it : mSkelAnimations[i]->_getNodeTrackList()) {
|
||||
Ogre::NodeAnimationTrack* track = it.second;
|
||||
Ogre::String trackName = track->getAssociatedNode()->getName();
|
||||
if (trackName == "mixamorig:Hips") {
|
||||
mHipsTracks[i] = track;
|
||||
} else if (trackName == "Root") {
|
||||
mRootTracks[i] = track;
|
||||
// mRootTracks[i]->removeAllKeyFrames();
|
||||
}
|
||||
}
|
||||
Ogre::Vector3 delta = Ogre::Vector3::ZERO;
|
||||
Ogre::Vector3 motion = Ogre::Vector3::ZERO;
|
||||
for(j = 0; j < mRootTracks[i]->getNumKeyFrames(); j++) {
|
||||
Ogre::Vector3 trans = mRootTracks[i]->getNodeKeyFrame(j)->getTranslate();
|
||||
if (j == 0)
|
||||
delta = trans;
|
||||
else
|
||||
delta = trans - motion;
|
||||
mRootTracks[i]->getNodeKeyFrame(j)->setTranslate(delta);
|
||||
motion = trans;
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
for(i = 0; i < NUM_ANIMS - 1; i++) {
|
||||
// need to cache
|
||||
int j;
|
||||
Ogre::String animName = mAnims[i]->getAnimationName();
|
||||
Ogre::Animation *anim = mSkeleton->getAnimation(animName);
|
||||
Ogre::NodeAnimationTrack *hips_track = nullptr, *root_track = nullptr;
|
||||
Ogre::Node *root_node = nullptr;
|
||||
for (const auto& it : anim->_getNodeTrackList()) {
|
||||
Ogre::NodeAnimationTrack* track = it.second;
|
||||
Ogre::String trackName = track->getAssociatedNode()->getName();
|
||||
std::cout << animName << " track: " << trackName << "\n";
|
||||
if (trackName == "mixamorig:Hips")
|
||||
hips_track = track;
|
||||
else if (trackName == "Root") {
|
||||
root_track = track;
|
||||
root_node = track->getAssociatedNode();
|
||||
}
|
||||
}
|
||||
assert(false);
|
||||
root_track->removeAllKeyFrames();
|
||||
std::cout << hips_track << " " << root_track << "\n";
|
||||
std::cout << hips_track->getNumKeyFrames() << " " << root_track->getNumKeyFrames() << "\n";
|
||||
assert(hips_track && root_track);
|
||||
Ogre::Vector3 delta = Ogre::Vector3::ZERO;
|
||||
for(j = 0; j < hips_track->getNumKeyFrames(); j++) {
|
||||
float timePos = hips_track->getNodeKeyFrame(j)->getTime();
|
||||
Ogre::Vector3 trans = hips_track->getNodeKeyFrame(j)->getTranslate();
|
||||
Ogre::Vector3 hips_trans(0, 0, 0);
|
||||
Ogre::Vector3 root_trans(0, 0, 0);
|
||||
hips_track->getNodeKeyFrame(j)->setTranslate(hips_trans);
|
||||
Ogre::TransformKeyFrame *nk = root_track->createNodeKeyFrame(timePos);
|
||||
nk->setTranslate(root_trans - delta);
|
||||
nk->setScale(Ogre::Vector3(1, 1, 1));
|
||||
nk->setRotation(Ogre::Quaternion());
|
||||
std::cout << animName << " delta: " << j << " " << timePos << " " << root_trans - delta << "\n";
|
||||
delta = root_trans;
|
||||
}
|
||||
for(j = 0; j < root_track->getNumKeyFrames(); j++) {
|
||||
float timePos = hips_track->getNodeKeyFrame(j)->getTime();
|
||||
Ogre::Vector3 root_trans = hips_track->getNodeKeyFrame(j)->getTranslate();
|
||||
std::cout << animName << " delta: root: " << j << " " << timePos << " " << root_trans << "\n";
|
||||
}
|
||||
}
|
||||
// assert(false);
|
||||
#endif
|
||||
setAnimation(ANIM_IDLE);
|
||||
}
|
||||
bool CharacterController::keyPressed(const OgreBites::KeyboardEvent& evt)
|
||||
{
|
||||
OgreBites::Keycode key = evt.keysym.sym;
|
||||
if (key == 'q' && (mAnimID == ANIM_IDLE)) {
|
||||
/* ... */
|
||||
mTimer = 0;
|
||||
} else if (key == 'e') {
|
||||
} else if (key == 'w')
|
||||
mKeyDirection.z = -1;
|
||||
else if (key == 'a')
|
||||
mKeyDirection.x = -1;
|
||||
else if (key == 's')
|
||||
mKeyDirection.z = 1;
|
||||
else if (key == 'd')
|
||||
mKeyDirection.x = 1;
|
||||
if (key == OgreBites::SDLK_LSHIFT)
|
||||
mRunning = true;
|
||||
if (!mKeyDirection.isZeroLength() && mAnimID == ANIM_IDLE) {
|
||||
if (mRunning)
|
||||
setAnimation(ANIM_RUN, true);
|
||||
else
|
||||
setAnimation(ANIM_WALK, true);
|
||||
// std::cout << "Walking\n";
|
||||
} else if (!mKeyDirection.isZeroLength() && mAnimID == ANIM_WALK && mRunning)
|
||||
setAnimation(ANIM_RUN);
|
||||
return true;
|
||||
}
|
||||
bool CharacterController::keyReleased(const OgreBites::KeyboardEvent& evt)
|
||||
{
|
||||
OgreBites::Keycode key = evt.keysym.sym;
|
||||
if (key == 'w' && mKeyDirection.z == -1) mKeyDirection.z = 0;
|
||||
else if (key == 'a' && mKeyDirection.x == -1) mKeyDirection.x = 0;
|
||||
else if (key == 's' && mKeyDirection.z == 1) mKeyDirection.z = 0;
|
||||
else if (key == 'd' && mKeyDirection.x == 1) mKeyDirection.x = 0;
|
||||
if (key == OgreBites::SDLK_LSHIFT)
|
||||
mRunning = false;
|
||||
|
||||
if (mKeyDirection.isZeroLength() && (mAnimID == ANIM_WALK || mAnimID == ANIM_RUN))
|
||||
setAnimation(ANIM_IDLE);
|
||||
else if (!mKeyDirection.isZeroLength() && mAnimID == ANIM_RUN && !mRunning)
|
||||
setAnimation(ANIM_WALK);
|
||||
|
||||
return true;
|
||||
}
|
||||
bool CharacterController::mouseMoved(const OgreBites::MouseMotionEvent& evt)
|
||||
{
|
||||
// update camera goal based on mouse movement
|
||||
updateCameraGoal(-0.18f * evt.xrel, -0.12f * evt.yrel, 0);
|
||||
return true;
|
||||
}
|
||||
bool CharacterController::mouseWheelRolled(const OgreBites::MouseWheelEvent& evt)
|
||||
{
|
||||
// update camera goal based on mouse movement
|
||||
updateCameraGoal(0, 0, -0.15f * evt.y);
|
||||
return true;
|
||||
}
|
||||
bool CharacterController::mousePressed(const OgreBites::MouseButtonEvent& evt)
|
||||
{
|
||||
std::cout << "Mouse press\n";
|
||||
return false;
|
||||
}
|
||||
void CharacterController::frameRendered(const Ogre::FrameEvent& evt)
|
||||
{
|
||||
updateBody(evt.timeSinceLastFrame);
|
||||
updateAnimations(evt.timeSinceLastFrame);
|
||||
updateCamera(evt.timeSinceLastFrame);
|
||||
if (evt.timeSinceLastFrame > 0)
|
||||
updateRootMotion(evt.timeSinceLastFrame);
|
||||
}
|
||||
bool CharacterController::frameStarted(const Ogre::FrameEvent& evt)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
void CharacterController::updateCameraGoal(Real deltaYaw, Real deltaPitch, Real deltaZoom)
|
||||
{
|
||||
mCameraPivot->yaw(Ogre::Degree(deltaYaw), Ogre::Node::TS_PARENT);
|
||||
if (!(mPivotPitch + deltaPitch > 25 && deltaPitch > 0) &&
|
||||
!(mPivotPitch + deltaPitch < -60 && deltaPitch < 0)) {
|
||||
mCameraPivot->pitch(Ogre::Degree(deltaPitch), Ogre::Node::TS_LOCAL);
|
||||
mPivotPitch += deltaPitch;
|
||||
}
|
||||
Real dist = mCameraGoal->_getDerivedPosition().distance(mCameraPivot->_getDerivedPosition());
|
||||
Real distChange = deltaZoom * dist;
|
||||
|
||||
// bound the zoom
|
||||
if (!(dist + distChange < 8 && distChange < 0) &&
|
||||
!(dist + distChange > 25 && distChange > 0))
|
||||
mCameraGoal->translate(0, 0, distChange, Ogre::Node::TS_LOCAL);
|
||||
}
|
||||
void CharacterController::updateBody(Real delta)
|
||||
{
|
||||
mGoalDirection = Ogre::Vector3::ZERO;
|
||||
if (mKeyDirection != Ogre::Vector3::ZERO) {
|
||||
// calculate actually goal direction in world based on player's key directions
|
||||
mGoalDirection += mKeyDirection.z * mCameraNode->getOrientation().zAxis();
|
||||
mGoalDirection += mKeyDirection.x * mCameraNode->getOrientation().xAxis();
|
||||
mGoalDirection.y = 0;
|
||||
mGoalDirection.normalise();
|
||||
|
||||
Ogre::Quaternion toGoal = mBodyNode->getOrientation().zAxis().getRotationTo(mGoalDirection);
|
||||
// calculate how much the character has to turn to face goal direction
|
||||
Real yawToGoal = toGoal.getYaw().valueDegrees();
|
||||
// this is how much the character CAN turn this frame
|
||||
Real yawAtSpeed = yawToGoal / Math::Abs(yawToGoal) * delta * TURN_SPEED;
|
||||
// reduce "turnability" if we're in midair
|
||||
// if (mBaseAnimID == ANIM_JUMP_LOOP) yawAtSpeed *= 0.2f;
|
||||
if (yawToGoal < 0)
|
||||
yawToGoal = std::min<Real>(0, std::max<Real>(yawToGoal, yawAtSpeed)); //yawToGoal = Math::Clamp<Real>(yawToGoal, yawAtSpeed, 0);
|
||||
else if (yawToGoal > 0)
|
||||
yawToGoal = std::max<Real>(0, std::min<Real>(yawToGoal, yawAtSpeed)); //yawToGoal = Math::Clamp<Real>(yawToGoal, 0, yawAtSpeed);
|
||||
mBodyNode->yaw(Ogre::Degree(yawToGoal));
|
||||
// move in current body direction (not the goal direction)
|
||||
// mBodyNode->translate(0, 0, delta * RUN_SPEED * mAnims[mAnimID]->getWeight(),
|
||||
// Ogre::Node::TS_LOCAL);
|
||||
#if 0
|
||||
if (mBaseAnimID == ANIM_JUMP_LOOP)
|
||||
{
|
||||
// if we're jumping, add a vertical offset too, and apply gravity
|
||||
mBodyNode->translate(0, mVerticalVelocity * deltaTime, 0, Node::TS_LOCAL);
|
||||
mVerticalVelocity -= GRAVITY * deltaTime;
|
||||
|
||||
Vector3 pos = mBodyNode->getPosition();
|
||||
if (pos.y <= CHAR_HEIGHT)
|
||||
{
|
||||
// if we've hit the ground, change to landing state
|
||||
pos.y = CHAR_HEIGHT;
|
||||
mBodyNode->setPosition(pos);
|
||||
setBaseAnimation(ANIM_JUMP_END, true);
|
||||
mTimer = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
void CharacterController::updateAnimations(Real delta)
|
||||
{
|
||||
int i, j, k;
|
||||
Real animSpeed = 1;
|
||||
mTimer += delta;
|
||||
if (mAnimID != ANIM_NONE) {
|
||||
if (mAnimID == ANIM_WALK)
|
||||
mAnims[mAnimID]->addTime(delta * 1.0f);
|
||||
else
|
||||
mAnims[mAnimID]->addTime(delta * animSpeed);
|
||||
}
|
||||
fadeAnimations(delta);
|
||||
}
|
||||
void CharacterController::updateRootMotion(Real delta)
|
||||
{
|
||||
Ogre::Vector3 boneMotion = mRootBone->getPosition();
|
||||
OgreAssert(delta > 0.0f, "Zero delta");
|
||||
#if 0
|
||||
Ogre::Vector3 motion = boneMotion - rootMotion;
|
||||
if (motion.squaredLength() > 0.1f * 0.1f)
|
||||
motion = Ogre::Vector3();
|
||||
rootMotion = boneMotion;
|
||||
#endif
|
||||
#if 0
|
||||
float mass = mRigidBody->getMass();
|
||||
std::cout << "Root bone position: " << boneMotion << "\n";
|
||||
std::cout << "body mass: " << mass << "\n";
|
||||
#endif
|
||||
/* Kinematic motion */
|
||||
Ogre::Quaternion rot = mBodyNode->getOrientation();
|
||||
Ogre::Vector3 gravity(0, -9.8, 0);
|
||||
Ogre::Vector3 velocity = rot * boneMotion / delta;
|
||||
velocity += gravity * delta;
|
||||
Ogre::Vector3 rotMotion = velocity * delta;
|
||||
btTransform from(convert(mBodyNode->getOrientation()), convert(mBodyNode->getPosition()));
|
||||
mBodyNode->setPosition(mBodyNode->getPosition() + rotMotion);
|
||||
// WorldData::get_singleton()->getWorld()->testBodyMotion(mRigidBody, from, Ogre::Bullet::convert(rotMotion), true,
|
||||
// nullptr, false, std::set<btCollisionObject *>());
|
||||
}
|
||||
void CharacterController::fadeAnimations(Real delta)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < NUM_ANIMS; i++) {
|
||||
if (mFadingIn[i])
|
||||
{
|
||||
// slowly fade this animation in until it has full weight
|
||||
Real newWeight = mAnims[i]->getWeight() + delta * ANIM_FADE_SPEED;
|
||||
mAnims[i]->setWeight(Math::Clamp<Real>(newWeight, 0, 1));
|
||||
if (newWeight >= 1)
|
||||
mFadingIn[i] = false;
|
||||
}
|
||||
else if (mFadingOut[i])
|
||||
{
|
||||
// slowly fade this animation out until it has no weight, and then disable it
|
||||
Real newWeight = mAnims[i]->getWeight() - delta * ANIM_FADE_SPEED;
|
||||
mAnims[i]->setWeight(Math::Clamp<Real>(newWeight, 0, 1));
|
||||
if (newWeight <= 0)
|
||||
{
|
||||
mAnims[i]->setEnabled(false);
|
||||
mFadingOut[i] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void CharacterController::updateCamera(Real delta)
|
||||
{
|
||||
// place the camera pivot roughly at the character's shoulder
|
||||
mCameraPivot->setPosition(mBodyNode->getPosition() + Ogre::Vector3::UNIT_Y * CAM_HEIGHT);
|
||||
// move the camera smoothly to the goal
|
||||
Ogre::Vector3 goalOffset = mCameraGoal->_getDerivedPosition() - mCameraNode->getPosition();
|
||||
mCameraNode->translate(goalOffset * delta * 9.0f);
|
||||
// always look at the pivot
|
||||
mCameraNode->lookAt(mCameraPivot->_getDerivedPosition(), Ogre::Node::TS_PARENT);
|
||||
}
|
||||
void CharacterController::setAnimation(AnimID id, bool reset)
|
||||
{
|
||||
assert(id >= 0 && id < NUM_ANIMS);
|
||||
if (mAnimID != ANIM_NONE) {
|
||||
mFadingIn[mAnimID] = false;
|
||||
mFadingOut[mAnimID] = true;
|
||||
}
|
||||
mAnimID = id;
|
||||
if (id != ANIM_NONE) {
|
||||
mAnims[id]->setEnabled(true);
|
||||
mAnims[id]->setWeight(0);
|
||||
mFadingOut[id] = false;
|
||||
mFadingIn[id] = true;
|
||||
if (reset)
|
||||
mAnims[id]->setTimePosition(0);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
bool CharacterController::recoverFromPenetration(btRigidBody *body,
|
||||
const btTransform &body_position,
|
||||
btScalar recover_movement_scale,
|
||||
bool infinite_inertia,
|
||||
btVector3 &delta_recover_movement,
|
||||
recoverResult *recover_result,
|
||||
const std::set<btCollisionObject *> &exclude)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CharacterController::bodyTestMotion(btRigidBody *body,
|
||||
const btTransform &from,
|
||||
const btVector3 &motion, bool infinite_inertia,
|
||||
textMotionResult *result,
|
||||
bool excludeRaycastShapes,
|
||||
std::set<btCollisionObject *> exclude)
|
||||
{
|
||||
int t;
|
||||
btTransform body_transform;
|
||||
btVector3 initial_recover_motion(0, 0, 0);
|
||||
// phase one - depenetration
|
||||
for (t = 0; t < RECOVERING_MOVEMENT_CYCLES; t++)
|
||||
if (!recoverFromPenetration(body,
|
||||
body_transform,
|
||||
RECOVERING_MOVEMENT_SCALE,
|
||||
infinite_inertia,
|
||||
initial_recover_motion,
|
||||
nullptr, exclude))
|
||||
break;
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
class KeyHandler : public OgreBites::InputListener
|
||||
{
|
||||
bool keyPressed(const OgreBites::KeyboardEvent& evt) override
|
||||
{
|
||||
if (evt.keysym.sym == OgreBites::SDLK_ESCAPE)
|
||||
{
|
||||
Ogre::Root::getSingleton().queueEndRendering();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
bool MainWorld::frameStarted(const Ogre::FrameEvent& evt)
|
||||
{
|
||||
WorldData::get_singleton()->update(evt.timeSinceLastFrame);
|
||||
return true;
|
||||
}
|
||||
class App
|
||||
: public OgreBites::ApplicationContext
|
||||
{
|
||||
Ogre::SceneNode *mCameraNode;
|
||||
Ogre::SceneManager *mScnMgr;
|
||||
std::unique_ptr<CharacterController> mCharacter;
|
||||
KeyHandler mKeyHandler;
|
||||
MainWorld mWorld;
|
||||
public:
|
||||
App();
|
||||
virtual ~App();
|
||||
@@ -28,6 +787,7 @@ public:
|
||||
}
|
||||
void createContent();
|
||||
void createCharacter();
|
||||
void setupWorld();
|
||||
};
|
||||
|
||||
App::App()
|
||||
@@ -64,34 +824,33 @@ void App::initCamera()
|
||||
// and tell it to render into the main window
|
||||
getRenderWindow()->addViewport(cam);
|
||||
}
|
||||
void App::setupWorld()
|
||||
{
|
||||
addInputListener(&mKeyHandler);
|
||||
mWorld.setup();
|
||||
getRoot()->addFrameListener(&mWorld);
|
||||
}
|
||||
void App::createCharacter()
|
||||
{
|
||||
|
||||
Ogre::Entity* ent = mScnMgr->createEntity("normal-male.glb");
|
||||
Ogre::SceneNode* node = mScnMgr->getRootSceneNode()->createChildSceneNode();
|
||||
node->attachObject(ent);
|
||||
|
||||
Ogre::Camera *cam = static_cast<Ogre::Camera *>(mCameraNode->getAttachedObject("tps_camera"));
|
||||
mCharacter = std::make_unique<CharacterController>(mCameraNode, cam, mScnMgr, &mWorld);
|
||||
// mInputListenerChain = TouchAgnosticInputListenerChain(getRenderWindow(), {&mKeyHandler, mCharacter.get()});
|
||||
addInputListener(mCharacter.get());
|
||||
WorldData::get_singleton()->initPagedWorld(cam);
|
||||
}
|
||||
void App::createContent()
|
||||
{
|
||||
// without light we would just get a black screen
|
||||
Ogre::Light* light = mScnMgr->createLight("MainLight");
|
||||
Ogre::SceneNode* lightNode = mScnMgr->getRootSceneNode()->createChildSceneNode();
|
||||
lightNode->setPosition(0, 10, 15);
|
||||
// lightNode->setPosition(0, 10, 15);
|
||||
lightNode->setDirection(Ogre::Vector3(0.55, -0.3, 0.75).normalisedCopy());
|
||||
lightNode->attachObject(light);
|
||||
|
||||
light->setType(Ogre::Light::LT_DIRECTIONAL);
|
||||
light->setDiffuseColour(Ogre::ColourValue::White);
|
||||
light->setSpecularColour(Ogre::ColourValue(0.4, 0.4, 0.4));
|
||||
mScnMgr->setSkyBox(true, "Skybox", 490);
|
||||
}
|
||||
class KeyHandler : public OgreBites::InputListener
|
||||
{
|
||||
bool keyPressed(const OgreBites::KeyboardEvent& evt) override
|
||||
{
|
||||
if (evt.keysym.sym == OgreBites::SDLK_ESCAPE)
|
||||
{
|
||||
Ogre::Root::getSingleton().queueEndRendering();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
App ctx;
|
||||
@@ -103,16 +862,20 @@ int main(int argc, char *argv[])
|
||||
// register our scene with the RTSS
|
||||
Ogre::RTShader::ShaderGenerator* shadergen = Ogre::RTShader::ShaderGenerator::getSingletonPtr();
|
||||
shadergen->addSceneManager(scnMgr);
|
||||
|
||||
WorldData::init(root, scnMgr);
|
||||
ctx.setWindowGrab(true);
|
||||
ctx.createContent();
|
||||
ctx.initCamera();
|
||||
ctx.setupWorld();
|
||||
ctx.createCharacter();
|
||||
// register for input events
|
||||
KeyHandler keyHandler;
|
||||
ctx.addInputListener(&keyHandler);
|
||||
// KeyHandler keyHandler;
|
||||
// ctx.addInputListener(&keyHandler);
|
||||
|
||||
ctx.getRoot()->startRendering();
|
||||
ctx.setWindowGrab(false);
|
||||
ctx.closeApp();
|
||||
WorldData::cleanup();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
109
CMakeLists.txt
@@ -15,25 +15,86 @@ set(CREATE_SCENES
|
||||
${CMAKE_SOURCE_DIR}/characters/male/vroid-normal-male.scene
|
||||
)
|
||||
|
||||
|
||||
# workaround horribly broken assimp cmake, fixed with assimp 5.1
|
||||
add_library(fix::assimp INTERFACE IMPORTED)
|
||||
set_target_properties(fix::assimp PROPERTIES
|
||||
INTERFACE_LINK_LIBRARIES "${ASSIMP_LIBRARIES};pugixml"
|
||||
INTERFACE_LINK_DIRECTORIES "${ASSIMP_LIBRARY_DIRS}"
|
||||
)
|
||||
file(GLOB TERRAIN_SRC src/terrain/*.cpp)
|
||||
|
||||
# The COMPONENTS part checks that OGRE was built the way we need it
|
||||
# The CONFIG flag makes sure we get OGRE instead of OGRE-next
|
||||
find_package(OGRE REQUIRED COMPONENTS Bites CONFIG)
|
||||
find_package(OGRE REQUIRED COMPONENTS Bites Bullet Paging CONFIG)
|
||||
find_package(ZLIB)
|
||||
find_package(SDL2)
|
||||
find_package(assimp)
|
||||
|
||||
find_package(Bullet)
|
||||
find_package(OgreProcedural REQUIRED CONFIG)
|
||||
|
||||
add_library(fix::OgreProcedural INTERFACE IMPORTED)
|
||||
set_target_properties(fix::OgreProcedural PROPERTIES
|
||||
INTERFACE_LINK_LIBRARIES "OgreProcedural"
|
||||
INTERFACE_LINK_DIRECTORIES "${CMAKE_PREFIX_PATH}/lib"
|
||||
)
|
||||
|
||||
|
||||
add_subdirectory(src/lua)
|
||||
|
||||
# add the source files as usual
|
||||
add_executable(0_Bootstrap Bootstrap.cpp)
|
||||
|
||||
# this also sets the includes and pulls third party dependencies
|
||||
target_link_libraries(0_Bootstrap OgreBites)
|
||||
target_link_libraries(0_Bootstrap OgreBites OgreBullet OgrePaging ${BULLET_DYNAMICS_LIBRARY} ${BULLET_COLLISION_LIBRARY} ${BULLET_MATH_LIBRARY})
|
||||
target_include_directories(0_Bootstrap PUBLIC OgreBites OgrePaging OgreBullet)
|
||||
add_dependencies(0_Bootstrap stage_files)
|
||||
|
||||
add_executable(GuiTest GuiTest.cpp ${TERRAIN_SRC})
|
||||
target_link_libraries(GuiTest OgreBites OgreBullet OgrePaging OgreTerrain ${OgreProcedural_LIBRARIES} ${BULLET_DYNAMICS_LIBRARY} ${BULLET_COLLISION_LIBRARY} ${BULLET_MATH_LIBRARY})
|
||||
target_include_directories(GuiTest PUBLIC OgreBites OgrePaging OgreBullet OgreTerrain ${OgreProcedural_INCLUDE_DIRS})
|
||||
add_dependencies(GuiTest stage_files import_buildings)
|
||||
|
||||
add_executable(Procedural Procedural.cpp ${TERRAIN_SRC})
|
||||
target_link_libraries(Procedural OgreBites OgreBullet OgrePaging OgreTerrain OgreProcedural::OgreProcedural ${BULLET_DYNAMICS_LIBRARY} ${BULLET_COLLISION_LIBRARY} ${BULLET_MATH_LIBRARY})
|
||||
target_include_directories(Procedural PUBLIC OgreBites OgrePaging OgreBullet OgreTerrain OgreProcedural::OgreProcedural ${CMAKE_PREFIX_PATH}/include/OgreProcedural)
|
||||
add_dependencies(Procedural stage_files import_buildings)
|
||||
|
||||
file(GLOB BUILDINGS_SRC ${CMAKE_SOURCE_DIR}/assets/blender/buildings/*.blend)
|
||||
set(BUILDING_OUTPUT_FILES)
|
||||
foreach(BUILDING_FILE ${BUILDINGS_SRC})
|
||||
get_filename_component(FILE_NAME ${BUILDING_FILE} NAME_WE)
|
||||
set(BUILDING_OUTPUT_FILE ${CMAKE_BINARY_DIR}/resources/buildings/${FILE_NAME}.gltf)
|
||||
add_custom_command(
|
||||
OUTPUT ${BUILDING_OUTPUT_FILE}
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/resources/buildings
|
||||
COMMAND ${BLENDER} ${BUILDING_FILE}
|
||||
-b -Y -P
|
||||
${CMAKE_SOURCE_DIR}/assets/blender/scripts/export_buildings.py
|
||||
-- ${BUILDING_OUTPUT_FILE}
|
||||
COMMAND touch ${BUILDING_OUTPUT_FILE}
|
||||
DEPENDS ${BUILDING_FILE})
|
||||
list(APPEND BUILDING_OUTPUT_FILES ${BUILDING_OUTPUT_FILE})
|
||||
endforeach()
|
||||
|
||||
add_custom_target(import_buildings ALL DEPENDS ${BUILDING_OUTPUT_FILES})
|
||||
|
||||
add_executable(TerrainTest terrain.cpp ${TERRAIN_SRC})
|
||||
target_link_libraries(TerrainTest OgreBites OgreBullet OgrePaging OgreTerrain lua ${BULLET_DYNAMICS_LIBRARY} ${BULLET_COLLISION_LIBRARY} ${BULLET_MATH_LIBRARY})
|
||||
target_include_directories(TerrainTest PUBLIC OgreBites OgrePaging OgreTerrain OgreBullet PRIVATE . src/terrain src/lua src/lua/lua-5.4.8/src)
|
||||
|
||||
file(GLOB LUA_SCRIPTS_SRC ${CMAKE_SOURCE_DIR}/lua-scripts/*.lua)
|
||||
set(LUA_SCRIPTS_OUTPUT)
|
||||
foreach(LUA_SCRIPT_FILE ${LUA_SCRIPTS_SRC})
|
||||
get_filename_component(FILE_NAME ${LUA_SCRIPT_FILE} NAME_WE)
|
||||
set(LUA_SCRIPT_OUTPUT_FILE ${CMAKE_BINARY_DIR}/lua-scripts/${FILE_NAME}.lua)
|
||||
add_custom_command(OUTPUT ${LUA_SCRIPT_OUTPUT_FILE}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LUA_SCRIPT_FILE} ${LUA_SCRIPT_OUTPUT_FILE}
|
||||
DEPENDS ${LUA_SCRIPT_FILE})
|
||||
list(APPEND LUA_SCRIPTS_OUTPUT ${LUA_SCRIPT_OUTPUT_FILE})
|
||||
endforeach()
|
||||
add_custom_target(stage_lua_scripts ALL DEPENDS ${LUA_SCRIPTS_OUTPUT})
|
||||
add_dependencies(TerrainTest stage_lua_scripts stage_files)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_BINARY_DIR}/resources.cfg
|
||||
@@ -46,8 +107,48 @@ add_custom_command(
|
||||
${CMAKE_BINARY_DIR}/resources/terrain
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/characters
|
||||
${CMAKE_BINARY_DIR}/characters
|
||||
# COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/lua-scripts
|
||||
# ${CMAKE_BINARY_DIR}/lua-scripts
|
||||
# COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/skybox
|
||||
# ${CMAKE_BINARY_DIR}/skybox
|
||||
# COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/resources/debug
|
||||
# ${CMAKE_BINARY_DIR}/resources/debug
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/resources.cfg)
|
||||
|
||||
set(SKYBOX_SRC
|
||||
early_morning_bk.jpg
|
||||
early_morning_dn.jpg
|
||||
early_morning_fr.jpg
|
||||
early_morning_lf.jpg
|
||||
early_morning_rt.jpg
|
||||
early_morning_up.jpg
|
||||
skybox.material
|
||||
)
|
||||
set(DEBUG_MATERIAL_SRC
|
||||
debug.frag
|
||||
debug.material
|
||||
debug.program
|
||||
debug.vert
|
||||
)
|
||||
|
||||
set(MATERIALS_OUTPUT)
|
||||
foreach(SKYBOX_FILE ${SKYBOX_SRC})
|
||||
set(OUTPUT_FILE ${CMAKE_BINARY_DIR}/skybox/${SKYBOX_FILE})
|
||||
set(INPUT_FILE ${CMAKE_SOURCE_DIR}/skybox/${SKYBOX_FILE})
|
||||
add_custom_command(OUTPUT ${OUTPUT_FILE}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${INPUT_FILE} ${OUTPUT_FILE}
|
||||
DEPENDS ${INPUT_FILE})
|
||||
list(APPEND MATERIALS_OUTPUT ${OUTPUT_FILE})
|
||||
endforeach()
|
||||
foreach(DEBUG_MATERIAL_FILE ${DEBUG_MATERIAL_SRC})
|
||||
set(OUTPUT_FILE ${CMAKE_BINARY_DIR}/resources/debug/${DEBUG_MATERIAL_FILE})
|
||||
set(INPUT_FILE ${CMAKE_SOURCE_DIR}/resources/debug/${DEBUG_MATERIAL_FILE})
|
||||
add_custom_command(OUTPUT ${OUTPUT_FILE}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${INPUT_FILE} ${OUTPUT_FILE}
|
||||
DEPENDS ${INPUT_FILE})
|
||||
list(APPEND MATERIALS_OUTPUT ${OUTPUT_FILE})
|
||||
endforeach()
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_SOURCE_DIR}/characters/female/vroid-normal-female.scene
|
||||
${CMAKE_SOURCE_DIR}/characters/male/vroid-normal-male.scene
|
||||
@@ -65,7 +166,7 @@ add_custom_command(
|
||||
${CMAKE_SOURCE_DIR}/assets/vroid/jane2-dress.vrm
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
|
||||
|
||||
add_custom_target(stage_files ALL DEPENDS ${CMAKE_BINARY_DIR}/resources.cfg)
|
||||
add_custom_target(stage_files ALL DEPENDS ${CMAKE_BINARY_DIR}/resources.cfg ${MATERIALS_OUTPUT})
|
||||
|
||||
add_custom_target(remove_scenes COMMAND rm -f ${CREATE_SCENES})
|
||||
|
||||
|
||||
874
GuiTest.cpp
Normal file
@@ -0,0 +1,874 @@
|
||||
#include <iostream>
|
||||
|
||||
#include <Ogre.h>
|
||||
#include <OgreApplicationContext.h>
|
||||
#include <OgreOverlaySystem.h>
|
||||
#include <OgreOverlayManager.h>
|
||||
#include <OgreImGuiOverlay.h>
|
||||
#include <OgreImGuiInputListener.h>
|
||||
#include <OgreTrays.h>
|
||||
#include <OgreTimer.h>
|
||||
|
||||
#include "src/terrain/terrain.h"
|
||||
class App;
|
||||
class SkyRenderer : public Ogre::SceneManager::Listener {
|
||||
protected:
|
||||
Ogre::SceneManager *mSceneManager;
|
||||
virtual void _updateRenderQueue(Ogre::RenderQueue *queue) = 0;
|
||||
|
||||
public:
|
||||
enum BoxPlane {
|
||||
BP_FRONT = 0,
|
||||
BP_BACK = 1,
|
||||
BP_LEFT = 2,
|
||||
BP_RIGHT = 3,
|
||||
BP_UP = 4,
|
||||
BP_DOWN = 5
|
||||
};
|
||||
|
||||
SkyRenderer(Ogre::SceneManager *owner)
|
||||
: mSceneManager(owner)
|
||||
, mSceneNode(0)
|
||||
, mEnabled(false)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~SkyRenderer()
|
||||
{
|
||||
setEnabled(false);
|
||||
if (mSceneNode)
|
||||
mSceneManager->destroySceneNode(mSceneNode);
|
||||
}
|
||||
|
||||
Ogre::SceneNode *mSceneNode;
|
||||
bool mEnabled;
|
||||
|
||||
void setEnabled(bool enable)
|
||||
{
|
||||
if (enable == mEnabled)
|
||||
return;
|
||||
mEnabled = enable;
|
||||
enable ? mSceneManager->addListener(this) :
|
||||
mSceneManager->removeListener(this);
|
||||
}
|
||||
void
|
||||
postFindVisibleObjects(Ogre::SceneManager *source,
|
||||
Ogre::SceneManager::IlluminationRenderStage irs,
|
||||
Ogre::Viewport *vp) override
|
||||
{
|
||||
// Queue skies, if viewport seems it
|
||||
if (!vp->getSkiesEnabled() ||
|
||||
irs == Ogre::SceneManager::IRS_RENDER_TO_TEXTURE)
|
||||
return;
|
||||
|
||||
if (!mEnabled || !mSceneNode)
|
||||
return;
|
||||
|
||||
// Update nodes
|
||||
// Translate the box by the camera position (constant distance)
|
||||
mSceneNode->setPosition(vp->getCamera()->getDerivedPosition());
|
||||
_updateRenderQueue(source->getRenderQueue());
|
||||
}
|
||||
};
|
||||
class SkyBoxRenderer : public SkyRenderer {
|
||||
std::unique_ptr<Ogre::ManualObject> mSkyBoxObj;
|
||||
|
||||
Ogre::Quaternion mSkyBoxOrientation;
|
||||
void _updateRenderQueue(Ogre::RenderQueue *queue) override
|
||||
{
|
||||
if (mSkyBoxObj->isVisible()) {
|
||||
mSkyBoxObj->_updateRenderQueue(queue);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
SkyBoxRenderer(Ogre::SceneManager *owner)
|
||||
: SkyRenderer(owner)
|
||||
{
|
||||
}
|
||||
Ogre::SceneManager::SkyBoxGenParameters mSkyBoxGenParameters;
|
||||
void create(const Ogre::String &materialName, Ogre::Real distance,
|
||||
uint8_t renderQueue, const Ogre::Quaternion &orientation,
|
||||
const Ogre::String &groupName)
|
||||
{
|
||||
Ogre::MaterialPtr m =
|
||||
Ogre::MaterialManager::getSingleton().getByName(
|
||||
materialName, groupName);
|
||||
OgreAssert(m, "Sky box material '" + materialName +
|
||||
"' not found.");
|
||||
// Ensure loaded
|
||||
m->load();
|
||||
|
||||
bool valid = m->getBestTechnique() &&
|
||||
m->getBestTechnique()->getNumPasses();
|
||||
#if 0
|
||||
if (valid) {
|
||||
Pass *pass = m->getBestTechnique()->getPass(0);
|
||||
valid = valid && pass->getNumTextureUnitStates() &&
|
||||
pass->getTextureUnitState(0)->getTextureType() ==
|
||||
TEX_TYPE_CUBE_MAP;
|
||||
}
|
||||
|
||||
if (!valid) {
|
||||
LogManager::getSingleton().logWarning(
|
||||
"skybox material " + materialName +
|
||||
" is not supported, defaulting");
|
||||
m = MaterialManager::getSingleton().getDefaultSettings();
|
||||
}
|
||||
#endif
|
||||
OgreAssert(valid, "Bad material" + materialName);
|
||||
|
||||
// Create node
|
||||
mSceneNode = mSceneManager->createSceneNode();
|
||||
|
||||
// Create object
|
||||
mSkyBoxObj = std::make_unique<Ogre::ManualObject>("SkyBox");
|
||||
mSkyBoxObj->setCastShadows(false);
|
||||
mSceneNode->attachObject(mSkyBoxObj.get());
|
||||
|
||||
mSkyBoxObj->setRenderQueueGroup(renderQueue);
|
||||
mSkyBoxObj->begin(materialName,
|
||||
Ogre::RenderOperation::OT_TRIANGLE_STRIP,
|
||||
groupName);
|
||||
|
||||
// rendering cube, only using 14 vertices
|
||||
const Ogre::Vector3 cube_strip[14] = {
|
||||
{ -1.f, 1.f, 1.f }, // Front-top-left
|
||||
{ 1.f, 1.f, 1.f }, // Front-top-right
|
||||
{ -1.f, -1.f, 1.f }, // Front-bottom-left
|
||||
{ 1.f, -1.f, 1.f }, // Front-bottom-right
|
||||
{ 1.f, -1.f, -1.f }, // Back-bottom-right
|
||||
{ 1.f, 1.f, 1.f }, // Front-top-right
|
||||
{ 1.f, 1.f, -1.f }, // Back-top-right
|
||||
{ -1.f, 1.f, 1.f }, // Front-top-left
|
||||
{ -1.f, 1.f, -1.f }, // Back-top-left
|
||||
{ -1.f, -1.f, 1.f }, // Front-bottom-left
|
||||
{ -1.f, -1.f, -1.f }, // Back-bottom-left
|
||||
{ 1.f, -1.f, -1.f }, // Back-bottom-right
|
||||
{ -1.f, 1.f, -1.f }, // Back-top-left
|
||||
{ 1.f, 1.f, -1.f } // Back-top-right
|
||||
};
|
||||
|
||||
for (const auto &vtx : cube_strip) {
|
||||
mSkyBoxObj->position(orientation * (vtx * distance));
|
||||
// Note UVs mirrored front/back
|
||||
mSkyBoxObj->textureCoord(vtx.normalisedCopy() *
|
||||
Ogre::Vector3(1, 1, -1));
|
||||
}
|
||||
|
||||
mSkyBoxObj->end();
|
||||
mSkyBoxGenParameters.skyBoxDistance = distance;
|
||||
}
|
||||
};
|
||||
|
||||
class EditUI : public Ogre::RenderTargetListener {
|
||||
App *m_app;
|
||||
Ogre::SceneManager *mScnMgr;
|
||||
Ogre::ImGuiOverlay *mGuiOverlay;
|
||||
OgreBites::ImGuiInputListener *mGuiListener;
|
||||
void
|
||||
preViewportUpdate(const Ogre::RenderTargetViewportEvent &evt) override
|
||||
{
|
||||
preview(evt);
|
||||
}
|
||||
|
||||
public:
|
||||
EditUI(App *app)
|
||||
: Ogre::RenderTargetListener()
|
||||
, m_app(app)
|
||||
{
|
||||
}
|
||||
|
||||
void position_editor(Ogre::SceneNode *node)
|
||||
{
|
||||
Ogre::Vector3 position = node->getPosition();
|
||||
float v[3] = { position.x, position.y, position.z };
|
||||
ImGui::InputFloat3("position", v);
|
||||
position.x = v[0];
|
||||
position.y = v[1];
|
||||
position.z = v[2];
|
||||
node->setPosition(position);
|
||||
}
|
||||
void orientation_editor(Ogre::SceneNode *node)
|
||||
{
|
||||
Ogre::Quaternion q = node->getOrientation();
|
||||
float yaw = Ogre::Radian(q.getYaw()).valueDegrees();
|
||||
float pitch = Ogre::Radian(q.getPitch()).valueDegrees();
|
||||
float roll = Ogre::Radian(q.getRoll()).valueDegrees();
|
||||
bool m1 = ImGui::InputFloat("yaw", &yaw);
|
||||
bool m2 = ImGui::InputFloat("pitch", &pitch);
|
||||
bool m3 = ImGui::InputFloat("roll", &roll);
|
||||
if (m1 || m2 || m3) {
|
||||
Ogre::Quaternion q1(Ogre::Radian(Ogre::Degree(yaw)),
|
||||
Ogre::Vector3::UNIT_Y);
|
||||
Ogre::Quaternion q2(Ogre::Degree(pitch),
|
||||
Ogre::Vector3::UNIT_X);
|
||||
Ogre::Quaternion q3(Ogre::Degree(roll),
|
||||
Ogre::Vector3::UNIT_Z);
|
||||
node->setOrientation(q1 * q2 * q3);
|
||||
}
|
||||
}
|
||||
void attachments_editor(Ogre::SceneNode *node)
|
||||
{
|
||||
const Ogre::SceneNode::ObjectMap &pmap =
|
||||
node->getAttachedObjects();
|
||||
int i;
|
||||
for (i = 0; i < pmap.size(); i++) {
|
||||
const Ogre::MovableObject *mobj = pmap[i];
|
||||
const Ogre::String &pname = mobj->getName();
|
||||
ImGui::Text("Name: %s", pname.c_str());
|
||||
}
|
||||
}
|
||||
std::vector<Ogre::String> glb_names;
|
||||
void init_glb_list()
|
||||
{
|
||||
int i;
|
||||
|
||||
const std::vector<Ogre::String> &groups =
|
||||
Ogre::ResourceGroupManager::getSingleton()
|
||||
.getResourceGroups();
|
||||
for (i = 0; i < groups.size(); i++) {
|
||||
std::vector<Ogre::String> names =
|
||||
*Ogre::ResourceGroupManager::getSingleton()
|
||||
.findResourceNames(groups[i], "*.glb");
|
||||
glb_names.insert(glb_names.end(), names.begin(),
|
||||
names.end());
|
||||
}
|
||||
}
|
||||
void buildings_editor();
|
||||
void buttons_panel();
|
||||
void preview(const Ogre::RenderTargetViewportEvent &evt);
|
||||
float panel_width;
|
||||
void initGui();
|
||||
};
|
||||
class App : public OgreBites::ApplicationContext {
|
||||
std::unique_ptr<Ogre::Bullet::DynamicsWorld> mDynWorld;
|
||||
std::unique_ptr<Ogre::Bullet::DebugDrawer> mDbgDraw;
|
||||
Ogre::SceneNode *mCameraNode;
|
||||
Ogre::SceneNode *mCameraPivot;
|
||||
Ogre::SceneNode *mCameraGoal;
|
||||
Ogre::Camera *mCamera;
|
||||
Ogre::Real mPivotPitch;
|
||||
Ogre::SceneManager *mScnMgr;
|
||||
OgreBites::InputListenerChain mInput;
|
||||
Ogre::Viewport *mViewport;
|
||||
EditUI m_edit_ui;
|
||||
TerrainSetup m_terrain;
|
||||
Ogre::Light *mSun;
|
||||
SkyBoxRenderer *sky;
|
||||
// OgreBites::TrayManager *mTrayMgr;
|
||||
class KeyboardListener : public OgreBites::InputListener,
|
||||
public Ogre::FrameListener {
|
||||
App *mApp;
|
||||
|
||||
public:
|
||||
Ogre::Vector3 motion;
|
||||
bool gui_active;
|
||||
Ogre::Timer fps_timer;
|
||||
bool fast;
|
||||
KeyboardListener(App *app)
|
||||
: OgreBites::InputListener()
|
||||
, Ogre::FrameListener()
|
||||
, mApp(app)
|
||||
, gui_active(false)
|
||||
, fast(false)
|
||||
{
|
||||
}
|
||||
bool keyPressed(const OgreBites::KeyboardEvent &evt) override
|
||||
{
|
||||
if (gui_active)
|
||||
return false;
|
||||
if (evt.keysym.sym == OgreBites::SDLK_ESCAPE) {
|
||||
gui_active = true;
|
||||
// std::cout << "Escape!\n";
|
||||
// Ogre::Root::getSingleton().queueEndRendering();
|
||||
mApp->setWindowGrab(false);
|
||||
}
|
||||
if (evt.keysym.sym == 'w')
|
||||
motion.z = -1.0f;
|
||||
if (evt.keysym.sym == 's')
|
||||
motion.z = 1.0f;
|
||||
if (evt.keysym.sym == 'a')
|
||||
motion.x = -1.0f;
|
||||
if (evt.keysym.sym == 'd')
|
||||
motion.x = 1.0f;
|
||||
if (evt.keysym.sym == OgreBites::SDLK_LSHIFT)
|
||||
fast = true;
|
||||
// std::cout << "motion: " << motion << "\n";
|
||||
return true;
|
||||
}
|
||||
bool keyReleased(const OgreBites::KeyboardEvent &evt) override
|
||||
{
|
||||
if (gui_active)
|
||||
return false;
|
||||
if (evt.keysym.sym == 'w' && motion.z < 0.0f)
|
||||
motion.z = 0.0f;
|
||||
if (evt.keysym.sym == 's' && motion.z > 0.0f)
|
||||
motion.z = 0.0f;
|
||||
if (evt.keysym.sym == 'a' && motion.x < 0.0f)
|
||||
motion.x = 0.0f;
|
||||
if (evt.keysym.sym == 'd' && motion.x > 0.0f)
|
||||
motion.x = 0.0f;
|
||||
if (evt.keysym.sym == OgreBites::SDLK_LSHIFT)
|
||||
fast = false;
|
||||
return true;
|
||||
}
|
||||
bool mouseMoved(const OgreBites::MouseMotionEvent &evt)
|
||||
{
|
||||
if (gui_active)
|
||||
return false;
|
||||
// update camera goal based on mouse movement
|
||||
mApp->updateCameraGoal(-0.18f * evt.xrel,
|
||||
-0.12f * evt.yrel, 0);
|
||||
return true;
|
||||
}
|
||||
bool mouseWheelRolled(const OgreBites::MouseWheelEvent &evt)
|
||||
{
|
||||
if (gui_active)
|
||||
return false;
|
||||
// update camera goal based on mouse movement
|
||||
mApp->updateCameraGoal(0, 0, -0.15f * evt.y);
|
||||
return true;
|
||||
}
|
||||
void update(float delta)
|
||||
{
|
||||
return;
|
||||
// float fade = (1.0f - delta) * 0.98f;
|
||||
// motion *= fade;
|
||||
}
|
||||
void frameRendered(const Ogre::FrameEvent &evt) override
|
||||
{
|
||||
if (fps_timer.getMilliseconds() > 1000.0f) {
|
||||
std::cout << "FPS: "
|
||||
<< mApp->getRenderWindow()
|
||||
->getStatistics()
|
||||
.lastFPS
|
||||
<< " ";
|
||||
std::cout << "Draw calls: "
|
||||
<< mApp->getRenderWindow()
|
||||
->getStatistics()
|
||||
.batchCount
|
||||
<< " ";
|
||||
fps_timer.reset();
|
||||
std::cout << "Drops: "
|
||||
<< mApp->getRenderWindow()
|
||||
->getStatistics()
|
||||
.vBlankMissCount
|
||||
<< "\n";
|
||||
fps_timer.reset();
|
||||
}
|
||||
update(evt.timeSinceLastFrame);
|
||||
if (!gui_active) {
|
||||
mApp->updateMotion(evt.timeSinceLastFrame);
|
||||
mApp->updateCamera(evt.timeSinceLastFrame);
|
||||
mApp->updateSun(evt.timeSinceLastFrame);
|
||||
mApp->updateTerrain(evt.timeSinceLastFrame);
|
||||
}
|
||||
}
|
||||
};
|
||||
KeyboardListener mKbd;
|
||||
|
||||
public:
|
||||
App()
|
||||
: OgreBites::ApplicationContext("GuiTest")
|
||||
, mKbd(this)
|
||||
, m_edit_ui(this)
|
||||
, mDynWorld(new Ogre::Bullet::DynamicsWorld(
|
||||
Ogre::Vector3(0, -9.8, 0)))
|
||||
, m_terrain(mDynWorld->getBtWorld())
|
||||
{
|
||||
}
|
||||
virtual ~App()
|
||||
{
|
||||
}
|
||||
void setup()
|
||||
{
|
||||
OgreBites::ApplicationContext::setup();
|
||||
Ogre::Root *root = getRoot();
|
||||
Ogre::SceneManager *scnMgr = root->createSceneManager();
|
||||
mScnMgr = scnMgr;
|
||||
Ogre::OverlaySystem *pOverlaySystem = getOverlaySystem();
|
||||
mScnMgr->addRenderQueueListener(pOverlaySystem);
|
||||
// mTrayMgr = new OgreBites::TrayManager("AppTrays",
|
||||
// getRenderWindow());
|
||||
mDbgDraw.reset(new Ogre::Bullet::DebugDrawer(
|
||||
mScnMgr->getRootSceneNode(), mDynWorld->getBtWorld()));
|
||||
}
|
||||
void locateResources()
|
||||
{
|
||||
OgreBites::ApplicationContext::locateResources();
|
||||
}
|
||||
|
||||
void initCamera()
|
||||
{
|
||||
mCameraNode = mScnMgr->getRootSceneNode()->createChildSceneNode(
|
||||
"CameraNode");
|
||||
mCameraNode->setPosition(0, 2, 3);
|
||||
mCameraNode->lookAt(Ogre::Vector3(0, 1, -1),
|
||||
Ogre::Node::TS_PARENT);
|
||||
|
||||
// create the camera
|
||||
mCamera = mScnMgr->createCamera("fps_camera");
|
||||
mCamera->setNearClipDistance(0.1f); // specific to this sample
|
||||
mCamera->setAutoAspectRatio(true);
|
||||
mCameraNode->attachObject(mCamera);
|
||||
|
||||
// and tell it to render into the main window
|
||||
mViewport = getRenderWindow()->addViewport(mCamera);
|
||||
mCameraPivot =
|
||||
mScnMgr->getRootSceneNode()->createChildSceneNode(
|
||||
"FPSCameraPivot");
|
||||
mCameraGoal = mCameraPivot->createChildSceneNode(
|
||||
"FPSCameraGoal", Ogre::Vector3(0, 2, 3));
|
||||
mCameraNode->setPosition(mCameraPivot->getPosition() +
|
||||
mCameraGoal->getPosition());
|
||||
mCameraPivot->setFixedYawAxis(true);
|
||||
mCameraGoal->setFixedYawAxis(true);
|
||||
mCameraNode->setFixedYawAxis(true);
|
||||
// our model is quite small, so reduce the clipping planes
|
||||
mCamera->setNearClipDistance(0.1f);
|
||||
mCamera->setFarClipDistance(700);
|
||||
|
||||
mPivotPitch = 0;
|
||||
// mKeyDirection = Ogre::Vector3::ZERO;
|
||||
// mVerticalVelocity = 0;
|
||||
Ogre::ManualObject *mobj =
|
||||
mScnMgr->createManualObject("cursorGen");
|
||||
|
||||
#if 0
|
||||
Ogre::MaterialPtr mat =
|
||||
Ogre::static_pointer_cast<Ogre::Material>(
|
||||
Ogre::MaterialManager::getSingleton()
|
||||
.createOrRetrieve("Debug/Red2",
|
||||
"General")
|
||||
.first);
|
||||
mat->removeAllTechniques();
|
||||
Ogre::Technique *tech = mat->createTechnique();
|
||||
tech->setDiffuse(Ogre::ColourValue(1, 0, 0, 1));
|
||||
tech->setName("Debug/S");
|
||||
tech->setDepthCheckEnabled(false);
|
||||
tech->setLightingEnabled(false);
|
||||
mobj->begin(mat, Ogre::RenderOperation::OT_LINE_LIST);
|
||||
#endif
|
||||
mobj->begin("Debug/Red", Ogre::RenderOperation::OT_LINE_LIST);
|
||||
mobj->position(0, 0, 0);
|
||||
mobj->colour(Ogre::ColourValue(1, 0, 0));
|
||||
mobj->position(0, 2, 0);
|
||||
mobj->colour(Ogre::ColourValue(1, 0, 0));
|
||||
mobj->position(-1, 1, 0);
|
||||
mobj->colour(Ogre::ColourValue(1, 0, 0));
|
||||
mobj->position(1, 1, 0);
|
||||
mobj->colour(Ogre::ColourValue(1, 0, 0));
|
||||
mobj->index(0);
|
||||
mobj->index(1);
|
||||
mobj->index(2);
|
||||
mobj->index(3);
|
||||
mobj->end();
|
||||
mCameraPivot->attachObject(mobj);
|
||||
}
|
||||
Ogre::SceneManager *getSceneManager()
|
||||
{
|
||||
return mScnMgr;
|
||||
}
|
||||
void updateMotion(float delta)
|
||||
{
|
||||
if (delta == 0.0f)
|
||||
return;
|
||||
Ogre::Vector3 move(mCameraNode->getOrientation().zAxis() *
|
||||
mKbd.motion.z);
|
||||
move += Ogre::Vector3(mCameraNode->getOrientation().xAxis() *
|
||||
mKbd.motion.x);
|
||||
move.y = 0.0f;
|
||||
float speed = 15.0f;
|
||||
if (mKbd.fast)
|
||||
speed = 40.0f;
|
||||
Ogre::Vector3 opos = mCameraPivot->getPosition();
|
||||
Ogre::Vector3 pos =
|
||||
mCameraPivot->getPosition() + move * speed * delta;
|
||||
float y = m_terrain.get_height(pos);
|
||||
pos.y = y;
|
||||
|
||||
mCameraPivot->translate(pos - opos);
|
||||
// mKbd.motion = Ogre::Vector3(0, 0, 0);
|
||||
// if (move.squaredLength() > 0)
|
||||
// std::cout << move << "\n";
|
||||
}
|
||||
void updateCamera(Ogre::Real delta)
|
||||
{
|
||||
if (delta == 0.0f)
|
||||
return;
|
||||
// place the camera pivot roughly at the character's shoulder
|
||||
// mCameraPivot->setPosition(mBodyNode->getPosition() +
|
||||
// Ogre::Vector3::UNIT_Y * CAM_HEIGHT);
|
||||
// move the camera smoothly to the goal
|
||||
Ogre::Vector3 goalOffset = mCameraGoal->_getDerivedPosition() -
|
||||
mCameraNode->getPosition();
|
||||
float l = goalOffset.squaredLength();
|
||||
Ogre::Vector3 v = goalOffset * 10.0 * delta;
|
||||
if (v.squaredLength() > l * 0.5f - delta)
|
||||
v = goalOffset * delta;
|
||||
mCameraNode->translate(v);
|
||||
// mCameraNode->translate(goalOffset);
|
||||
// always look at the pivot
|
||||
mCameraNode->lookAt(mCameraPivot->_getDerivedPosition(),
|
||||
Ogre::Node::TS_PARENT);
|
||||
}
|
||||
void updateCameraGoal(Ogre::Real deltaYaw, Ogre::Real deltaPitch,
|
||||
Ogre::Real deltaZoom)
|
||||
{
|
||||
mCameraPivot->yaw(Ogre::Degree(deltaYaw),
|
||||
Ogre::Node::TS_PARENT);
|
||||
if (!(mPivotPitch + deltaPitch > 25 && deltaPitch > 0) &&
|
||||
!(mPivotPitch + deltaPitch < -60 && deltaPitch < 0)) {
|
||||
mCameraPivot->pitch(Ogre::Degree(deltaPitch),
|
||||
Ogre::Node::TS_LOCAL);
|
||||
mPivotPitch += deltaPitch;
|
||||
}
|
||||
Ogre::Real dist = mCameraGoal->_getDerivedPosition().distance(
|
||||
mCameraPivot->_getDerivedPosition());
|
||||
Ogre::Real distChange = deltaZoom * dist * 0.5f;
|
||||
if (distChange > 0 && dist + distChange > 30)
|
||||
distChange *= 0.3f;
|
||||
if (distChange < 0 && dist + distChange < 5)
|
||||
distChange *= 0.2f;
|
||||
|
||||
// bound the zoom
|
||||
if (!(dist + distChange < 3 && distChange < 0) &&
|
||||
!(dist + distChange > 40 && distChange > 0))
|
||||
mCameraGoal->translate(0, 0, distChange,
|
||||
Ogre::Node::TS_LOCAL);
|
||||
Ogre::Vector3 mh = mCameraGoal->_getDerivedPosition();
|
||||
float h = m_terrain.get_height(mh);
|
||||
if (h + 3 > mh.y)
|
||||
mCameraGoal->translate(0, 10.0f * deltaZoom, distChange,
|
||||
Ogre::Node::TS_LOCAL);
|
||||
}
|
||||
Ogre::SceneNode *mSunGoal;
|
||||
Ogre::SceneNode *mSunNode;
|
||||
Ogre::SceneNode *mSunTarget;
|
||||
Ogre::Timer mSunUpdate;
|
||||
void createSun()
|
||||
{
|
||||
Ogre::Light *light = mScnMgr->createLight("Sun");
|
||||
mSunNode = mScnMgr->getRootSceneNode()->createChildSceneNode(
|
||||
"SunPivot");
|
||||
mSunGoal = mScnMgr->getRootSceneNode()->createChildSceneNode(
|
||||
"SunGoal");
|
||||
mSunTarget = mSunGoal->createChildSceneNode(
|
||||
"SunGoalTarget",
|
||||
Ogre::Vector3(100.0f, -400.0f, -400.0f),
|
||||
Ogre::Quaternion::IDENTITY);
|
||||
// mSunNode->setAutoTracking(true, sun_target);
|
||||
// lightNode->setPosition(0, 10, 15);
|
||||
mSunNode->attachObject(light);
|
||||
light->setType(Ogre::Light::LT_DIRECTIONAL);
|
||||
light->setDiffuseColour(Ogre::ColourValue::White);
|
||||
light->setSpecularColour(Ogre::ColourValue(0.4, 0.4, 0.4));
|
||||
mSunNode->setDirection(Ogre::Vector3(100.0f, -400.0f, -400.f));
|
||||
mSun = light;
|
||||
}
|
||||
void updateSun(float delta)
|
||||
{
|
||||
static const float sun_speed = 1.0f;
|
||||
float uangle = M_PI * 2.0f / 24.0f / 60.0f;
|
||||
mSunNode->pitch(Ogre::Radian(uangle) * sun_speed * delta);
|
||||
if (mSunUpdate.getMilliseconds() > 1000) {
|
||||
Ogre::TerrainGlobalOptions::getSingleton()
|
||||
.setCompositeMapAmbient(
|
||||
mScnMgr->getAmbientLight());
|
||||
Ogre::TerrainGlobalOptions::getSingleton()
|
||||
.setCompositeMapDiffuse(
|
||||
mSun->getDiffuseColour());
|
||||
Ogre::TerrainGlobalOptions::getSingleton()
|
||||
.setLightMapDirection(
|
||||
mSun->getDerivedDirection());
|
||||
std::cout << "sun pitch: "
|
||||
<< mSunNode->getOrientation().getPitch()
|
||||
<< "\n";
|
||||
mSunUpdate.reset();
|
||||
}
|
||||
if (mSunNode->getOrientation().getPitch().valueRadians() > 0)
|
||||
mScnMgr->setAmbientLight(
|
||||
Ogre::ColourValue(0.0f, 0.0f, 0.2f, 1.0f));
|
||||
else
|
||||
mScnMgr->setAmbientLight(
|
||||
Ogre::ColourValue(0.2f, 0.2f, 0.2f, 1.0f));
|
||||
}
|
||||
Ogre::Timer mTerrainUpd;
|
||||
void updateTerrain(float delta)
|
||||
{
|
||||
mDbgDraw->update();
|
||||
#if 0
|
||||
if (mTerrainUpd.getMilliseconds() > 1000) {
|
||||
m_terrain.create_colliders();
|
||||
mTerrainUpd.reset();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
void createContent()
|
||||
{
|
||||
m_edit_ui.init_glb_list();
|
||||
m_edit_ui.initGui();
|
||||
createSun();
|
||||
mInput = OgreBites::InputListenerChain(
|
||||
{ getImGuiInputListener(), &mKbd });
|
||||
addInputListener(&mInput);
|
||||
getRoot()->addFrameListener(&mKbd);
|
||||
// mTrayMgr->showCursor();
|
||||
|
||||
// OgreBites::TrayManager *mTrayMgr = new OgreBites::TrayManager(
|
||||
// "InterfaceName", getRenderWindow());
|
||||
// mScnMgr->setSkyBox(true, "Skybox/Dynamic", 490);
|
||||
// /* mCamera->getCameraToViewportRay(left, top); */
|
||||
sky = new SkyBoxRenderer(getSceneManager());
|
||||
bool drawFirst = true;
|
||||
uint8_t renderQueue = drawFirst ?
|
||||
Ogre::RENDER_QUEUE_SKIES_EARLY :
|
||||
Ogre::RENDER_QUEUE_SKIES_LATE;
|
||||
sky->create("Skybox/Dynamic", 490, renderQueue,
|
||||
Ogre::Quaternion::IDENTITY,
|
||||
Ogre::ResourceGroupManager::
|
||||
AUTODETECT_RESOURCE_GROUP_NAME);
|
||||
sky->setEnabled(true);
|
||||
|
||||
Ogre::MaterialPtr m =
|
||||
Ogre::MaterialManager::getSingleton().getByName(
|
||||
"Skybox/Dynamic", "General");
|
||||
OgreAssert(m, "Sky box material not found.");
|
||||
m->load();
|
||||
Ogre::MeshManager::getSingleton().createPlane(
|
||||
"water",
|
||||
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||
Ogre::Plane(Ogre::Vector3::UNIT_Y, 0), 100, 100, 100,
|
||||
100, true, 1, 100, 100, Ogre::Vector3::UNIT_Z);
|
||||
|
||||
// create a floor entity, give it a material, and place it at the origin
|
||||
Ogre::Entity *water = mScnMgr->createEntity("Water", "water");
|
||||
water->setMaterialName("Water");
|
||||
mScnMgr->getRootSceneNode()
|
||||
->createChildSceneNode("Water")
|
||||
->attachObject(water);
|
||||
}
|
||||
void create_entity_node(const Ogre::String &name, int key)
|
||||
{
|
||||
Ogre::Entity *ent = mScnMgr->createEntity(name);
|
||||
Ogre::SceneNode *pnode =
|
||||
mScnMgr->getRootSceneNode()->createChildSceneNode(
|
||||
"ent:" + name +
|
||||
Ogre::StringConverter::toString(key),
|
||||
mCameraPivot->getPosition(),
|
||||
mCameraPivot->getOrientation());
|
||||
pnode->attachObject(ent);
|
||||
Ogre::Quaternion q = pnode->getOrientation();
|
||||
Ogre::Radian yaw = q.getYaw();
|
||||
Ogre::Quaternion nq(yaw, Ogre::Vector3(0, 1, 0));
|
||||
pnode->setOrientation(nq);
|
||||
mKbd.gui_active = false;
|
||||
setWindowGrab(true);
|
||||
}
|
||||
bool get_gui_active()
|
||||
{
|
||||
return mKbd.gui_active;
|
||||
}
|
||||
void set_gui_active(bool active)
|
||||
{
|
||||
mKbd.gui_active = active;
|
||||
}
|
||||
Ogre::Camera *getCamera()
|
||||
{
|
||||
return mCamera;
|
||||
}
|
||||
void setupTerrain()
|
||||
{
|
||||
m_terrain.setupTerrain(mCamera, mSun, mDynWorld.get(),
|
||||
mDbgDraw.get());
|
||||
}
|
||||
};
|
||||
|
||||
void EditUI::buildings_editor()
|
||||
{
|
||||
int i;
|
||||
ImVec2 size = ImGui::GetMainViewport()->Size;
|
||||
float window_width = size.x * 0.2f;
|
||||
if (window_width > panel_width)
|
||||
window_width = panel_width;
|
||||
float window_height = size.y * 0.5 - 20;
|
||||
ImGui::SetNextWindowPos(ImVec2(0, 0), ImGuiCond_Always);
|
||||
ImGui::SetNextWindowSize(ImVec2(window_width, window_height),
|
||||
ImGuiCond_Always);
|
||||
ImGui::Begin("Droppings...");
|
||||
for (i = 0; i < glb_names.size(); i++) {
|
||||
Ogre::String id_button = "Create entity: " + glb_names[i] +
|
||||
"##ent:" + glb_names[i];
|
||||
if (ImGui::Button(id_button.c_str())) {
|
||||
m_app->create_entity_node(glb_names[i], i);
|
||||
}
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
void EditUI::buttons_panel()
|
||||
{
|
||||
ImVec2 size = ImGui::GetMainViewport()->Size;
|
||||
float window_width = size.x * 0.2f;
|
||||
if (window_width > panel_width)
|
||||
window_width = panel_width;
|
||||
float window_height = size.y * 0.5f - 20;
|
||||
ImGui::SetNextWindowPos(ImVec2(0, size.y * 0.5f + 20),
|
||||
ImGuiCond_Always);
|
||||
ImGui::SetNextWindowSize(ImVec2(window_width, window_height),
|
||||
ImGuiCond_Always);
|
||||
ImGui::Begin("Dumb and Stupid");
|
||||
if (!m_app->get_gui_active())
|
||||
m_app->setWindowGrab(true);
|
||||
if (ImGui::Button("Shitty Quit button"))
|
||||
Ogre::Root::getSingleton().queueEndRendering();
|
||||
if (ImGui::Button("Chick-chick")) {
|
||||
m_app->set_gui_active(false);
|
||||
m_app->setWindowGrab(true);
|
||||
}
|
||||
ImGui::Text("We do stoopid...");
|
||||
ImGui::End();
|
||||
}
|
||||
void EditUI::preview(const Ogre::RenderTargetViewportEvent &evt)
|
||||
{
|
||||
int i;
|
||||
Ogre::ImGuiOverlay::NewFrame();
|
||||
if (m_app->get_gui_active()) {
|
||||
buttons_panel();
|
||||
buildings_editor();
|
||||
ImVec2 size = ImGui::GetMainViewport()->Size;
|
||||
float window_width = size.x * 0.2f;
|
||||
if (window_width > panel_width)
|
||||
window_width = panel_width;
|
||||
float window_height = size.y * 0.5f - 20;
|
||||
ImGui::SetNextWindowPos(ImVec2(size.x - window_width,
|
||||
size.y * 0.5f + 20),
|
||||
ImGuiCond_Always);
|
||||
ImGui::SetNextWindowSize(ImVec2(window_width, window_height),
|
||||
ImGuiCond_Always);
|
||||
// ImGui::Begin("Dumb and Stupid", &mKbd.gui_active);
|
||||
ImGui::Begin("Panel...");
|
||||
std::deque<Ogre::SceneNode *> tree_input_queue,
|
||||
tree_output_queue;
|
||||
std::vector<Ogre::SceneNode *> tree_list;
|
||||
tree_input_queue.push_back(mScnMgr->getRootSceneNode());
|
||||
tree_input_queue.push_back(nullptr);
|
||||
std::set<Ogre::SceneNode *> visited;
|
||||
while (true) {
|
||||
int new_nodes_count = 0;
|
||||
while (!tree_input_queue.empty()) {
|
||||
int child;
|
||||
Ogre::SceneNode *item =
|
||||
tree_input_queue.front();
|
||||
tree_input_queue.pop_front();
|
||||
if (item && visited.find(item) ==
|
||||
visited.end()) { // new node
|
||||
new_nodes_count++;
|
||||
tree_output_queue.push_back(item);
|
||||
visited.insert(item);
|
||||
const Ogre::Node::ChildNodeMap
|
||||
&children = item->getChildren();
|
||||
for (child = 0; child < children.size();
|
||||
child++) {
|
||||
tree_output_queue.push_back(
|
||||
static_cast<Ogre::SceneNode
|
||||
*>(
|
||||
children[child]));
|
||||
tree_output_queue.push_back(
|
||||
nullptr);
|
||||
}
|
||||
} else
|
||||
tree_output_queue.push_back(item);
|
||||
}
|
||||
if (new_nodes_count == 0)
|
||||
break;
|
||||
tree_input_queue = tree_output_queue;
|
||||
tree_output_queue.clear();
|
||||
}
|
||||
tree_list.insert(tree_list.begin(), tree_output_queue.begin(),
|
||||
tree_output_queue.end());
|
||||
int count = 0;
|
||||
int depth = 0;
|
||||
std::vector<int> check_depth;
|
||||
int max_depth = 0;
|
||||
check_depth.push_back(0);
|
||||
for (count = 0; count < tree_list.size(); count++) {
|
||||
int t;
|
||||
|
||||
Ogre::SceneNode *node = tree_list[count];
|
||||
if (node && max_depth >= depth) {
|
||||
Ogre::String name = node->getName();
|
||||
if (name.length() == 0) {
|
||||
name = "Node #" +
|
||||
Ogre::StringConverter::toString(
|
||||
count);
|
||||
}
|
||||
if (ImGui::TreeNode(name.c_str())) {
|
||||
check_depth.push_back(max_depth);
|
||||
max_depth++;
|
||||
ImGui::Text(
|
||||
"%s",
|
||||
(name + "##caption").c_str());
|
||||
position_editor(node);
|
||||
ImGui::Separator();
|
||||
orientation_editor(node);
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Attachments");
|
||||
attachments_editor(node);
|
||||
}
|
||||
} else if (!node && max_depth >= depth) {
|
||||
max_depth = check_depth.back();
|
||||
check_depth.pop_back();
|
||||
ImGui::TreePop();
|
||||
}
|
||||
if (tree_list[count])
|
||||
depth++;
|
||||
else
|
||||
depth--;
|
||||
}
|
||||
ImGui::Spacing();
|
||||
ImGui::End();
|
||||
}
|
||||
}
|
||||
void EditUI::initGui()
|
||||
{
|
||||
mScnMgr = m_app->getSceneManager();
|
||||
float vpScale = m_app->getDisplayDPI() / 96 *
|
||||
(float)m_app->getRenderWindow()->getWidth() / 1280;
|
||||
panel_width =
|
||||
380.0f * (float)m_app->getRenderWindow()->getWidth() / 1280;
|
||||
Ogre::OverlayManager::getSingleton().setPixelRatio(vpScale);
|
||||
mGuiOverlay = m_app->initialiseImGui();
|
||||
// float vpScale =
|
||||
// Ogre::OverlayManager::getSingleton().getPixelRatio();
|
||||
ImGui::GetIO().FontGlobalScale = std::round(vpScale);
|
||||
mGuiOverlay->setZOrder(300);
|
||||
mGuiOverlay->show();
|
||||
m_app->getRenderWindow()->addListener(this);
|
||||
}
|
||||
int main()
|
||||
{
|
||||
App ctx;
|
||||
ctx.initApp();
|
||||
// ctx.runRenderingSettingsDialog();
|
||||
// get a pointer to the already created root
|
||||
Ogre::Root *root = ctx.getRoot();
|
||||
Ogre::SceneManager *scnMgr = ctx.getSceneManager();
|
||||
|
||||
// register our scene with the RTSS
|
||||
Ogre::RTShader::ShaderGenerator *shadergen =
|
||||
Ogre::RTShader::ShaderGenerator::getSingletonPtr();
|
||||
shadergen->addSceneManager(scnMgr);
|
||||
ctx.setWindowGrab(true);
|
||||
ctx.initCamera();
|
||||
ctx.createContent();
|
||||
ctx.setupTerrain();
|
||||
// register for input events
|
||||
// KeyHandler keyHandler;
|
||||
// ctx.addInputListener(&keyHandler);
|
||||
|
||||
ctx.getRoot()->startRendering();
|
||||
ctx.setWindowGrab(false);
|
||||
ctx.closeApp();
|
||||
return 0;
|
||||
}
|
||||
984
Procedural.cpp
Normal file
@@ -0,0 +1,984 @@
|
||||
// This file is part of the OGRE project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at https://www.ogre3d.org/licensing.
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
#include <iostream>
|
||||
|
||||
#include "Ogre.h"
|
||||
#include "OgreApplicationContext.h"
|
||||
#include "Bullet/OgreBullet.h"
|
||||
#include "BulletCollision/CollisionDispatch/btGhostObject.h"
|
||||
#include "btKinematicCharacterController.h"
|
||||
#include "LinearMath/btTransform.h"
|
||||
#include "OgrePageManager.h"
|
||||
#include "Procedural.h"
|
||||
|
||||
#define CAM_HEIGHT 1.6f // height of camera above character's center of mass
|
||||
#define RUN_SPEED 17 // character running speed in units per second
|
||||
#define TURN_SPEED 500.0f // character turning in degrees per second
|
||||
#define ANIM_FADE_SPEED \
|
||||
7.5f // animation crossfade speed in % of full weight per second
|
||||
using Real = Ogre::Real;
|
||||
using Math = Ogre::Math;
|
||||
|
||||
class WorldData {
|
||||
std::unique_ptr<Ogre::Bullet::DynamicsWorld> mDynWorld;
|
||||
std::unique_ptr<Ogre::Bullet::DebugDrawer> mDbgDraw;
|
||||
std::unique_ptr<Ogre::Root> mRoot;
|
||||
std::unique_ptr<Ogre::SceneManager> mScnMgr;
|
||||
std::unique_ptr<btDynamicsWorld> mbtWorld;
|
||||
std::unique_ptr<Ogre::PageManager> mPageManager;
|
||||
Ogre::PagedWorld *mPagedWorld;
|
||||
|
||||
private:
|
||||
static WorldData *singleton;
|
||||
class DummyPageProvider : public Ogre::PageProvider {
|
||||
public:
|
||||
bool
|
||||
prepareProceduralPage(Ogre::Page *page,
|
||||
Ogre::PagedWorldSection *section) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool
|
||||
loadProceduralPage(Ogre::Page *page,
|
||||
Ogre::PagedWorldSection *section) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool
|
||||
unloadProceduralPage(Ogre::Page *page,
|
||||
Ogre::PagedWorldSection *section) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool unprepareProceduralPage(
|
||||
Ogre::Page *page,
|
||||
Ogre::PagedWorldSection *section) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
DummyPageProvider mDummyPageProvider;
|
||||
|
||||
WorldData(Ogre::Root *root, Ogre::SceneManager *scnMgr)
|
||||
: mDynWorld(new Ogre::Bullet::DynamicsWorld(
|
||||
Ogre::Vector3(0, -9.8, 0)))
|
||||
, mDbgDraw(new Ogre::Bullet::DebugDrawer(
|
||||
scnMgr->getRootSceneNode(), mDynWorld->getBtWorld()))
|
||||
, mRoot(root)
|
||||
, mScnMgr(scnMgr)
|
||||
, mbtWorld(mDynWorld->getBtWorld())
|
||||
, mPageManager(nullptr)
|
||||
, mPagedWorld(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
static void init(Ogre::Root *root, Ogre::SceneManager *scnMgr)
|
||||
{
|
||||
singleton = new WorldData(root, scnMgr);
|
||||
}
|
||||
static WorldData *get_singleton()
|
||||
{
|
||||
return singleton;
|
||||
}
|
||||
static void cleanup()
|
||||
{
|
||||
if (singleton)
|
||||
delete singleton;
|
||||
singleton = nullptr;
|
||||
}
|
||||
Ogre::SceneManager *getSceneManager()
|
||||
{
|
||||
return mScnMgr.get();
|
||||
}
|
||||
Ogre::Root *getRoot()
|
||||
{
|
||||
return mRoot.get();
|
||||
}
|
||||
void createTrimesh(Ogre::Entity *entity)
|
||||
{
|
||||
}
|
||||
btPairCachingGhostObject *addGhostObject(Ogre::Entity *ent,
|
||||
btCollisionShape *shape,
|
||||
int group = 1,
|
||||
int mask = 0xFFFF)
|
||||
{
|
||||
btDynamicsWorld *world = mDynWorld->getBtWorld();
|
||||
Ogre::SceneNode *node = ent->getParentSceneNode();
|
||||
btPairCachingGhostObject *ghost =
|
||||
new btPairCachingGhostObject();
|
||||
ghost->setCollisionShape(shape);
|
||||
ghost->setCollisionFlags(
|
||||
ghost->getCollisionFlags() |
|
||||
btCollisionObject::CF_NO_CONTACT_RESPONSE |
|
||||
btCollisionObject::CF_CHARACTER_OBJECT);
|
||||
getWorld()->attachCollisionObject(ghost, ent, group, mask);
|
||||
#if 0
|
||||
getBtWorld()
|
||||
->getBroadphase()->getOverlappingPairCache()
|
||||
->setInternalGhostPairCallback(new btGhostPairCallback());
|
||||
ghost->setUserPointer(new EntityCollisionListener{ent, nullptr});
|
||||
#endif
|
||||
return ghost;
|
||||
}
|
||||
btRigidBody *addRigidBody(float mass, Ogre::Entity *ent,
|
||||
Ogre::Bullet::ColliderType ct, int group = 1,
|
||||
int mask = 0xFFFF)
|
||||
{
|
||||
btDynamicsWorld *world = mDynWorld->getBtWorld();
|
||||
Ogre::SceneNode *node = ent->getParentSceneNode();
|
||||
Ogre::Bullet::RigidBodyState *state =
|
||||
new Ogre::Bullet::RigidBodyState(node);
|
||||
btCollisionShape *cs;
|
||||
btCollisionShape *shape;
|
||||
btVector3 inertia(0, 0, 0);
|
||||
switch (ct) {
|
||||
case Ogre::Bullet::CT_TRIMESH: {
|
||||
cs = Ogre::Bullet::createTrimeshCollider(ent);
|
||||
if (mass != 0)
|
||||
cs->calculateLocalInertia(mass, inertia);
|
||||
} break;
|
||||
case Ogre::Bullet::CT_CAPSULE: {
|
||||
cs = new btCompoundShape();
|
||||
btScalar height = 1.0f;
|
||||
btScalar radius = 0.3f;
|
||||
shape = new btCapsuleShape(radius,
|
||||
2 * height - 2 * radius);
|
||||
btTransform transform;
|
||||
transform.setIdentity();
|
||||
transform.setOrigin(btVector3(0, 1, 0));
|
||||
static_cast<btCompoundShape *>(cs)->addChildShape(
|
||||
transform, shape);
|
||||
btScalar masses[1] = { mass };
|
||||
btTransform principal;
|
||||
static_cast<btCompoundShape *>(cs)
|
||||
->calculatePrincipalAxisTransform(
|
||||
masses, principal, inertia);
|
||||
} break;
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
btRigidBody *body = new btRigidBody(mass, state, cs, inertia);
|
||||
getWorld()->attachRigidBody(body, ent, nullptr, group, mask);
|
||||
#if 0
|
||||
body->setUserPointer(new EntityCollisionListener{ent, nullptr});
|
||||
// btRigidBody *body = mDynWorld->addRigidBody(0, ent, Ogre::Bullet::CT_TRIMESH);
|
||||
#endif
|
||||
return body;
|
||||
}
|
||||
btRigidBody *addKinematicRigidBody(float mass, Ogre::Entity *ent,
|
||||
Ogre::Bullet::ColliderType ct,
|
||||
int group = 1, int mask = 0xFFFF)
|
||||
{
|
||||
return mDynWorld->addKinematicRigidBody(ent, ct, group, mask);
|
||||
}
|
||||
btDynamicsWorld *getBtWorld()
|
||||
{
|
||||
return mDynWorld->getBtWorld();
|
||||
}
|
||||
Ogre::Bullet::DynamicsWorld *getWorld()
|
||||
{
|
||||
return mDynWorld.get();
|
||||
}
|
||||
void update(float delta)
|
||||
{
|
||||
WorldData::get_singleton()->getBtWorld()->stepSimulation(delta,
|
||||
10);
|
||||
mDbgDraw->update();
|
||||
}
|
||||
void initPagedWorld(Ogre::Camera *camera)
|
||||
{
|
||||
mPageManager = std::make_unique<Ogre::PageManager>();
|
||||
mPageManager->setPageProvider(&mDummyPageProvider);
|
||||
mPageManager->addCamera(camera);
|
||||
mPageManager->setDebugDisplayLevel(0);
|
||||
mPagedWorld = mPageManager->createWorld();
|
||||
}
|
||||
};
|
||||
WorldData *WorldData::singleton = nullptr;
|
||||
|
||||
class MainWorld : public Ogre::FrameListener {
|
||||
btRigidBody *mFloorBody;
|
||||
|
||||
public:
|
||||
void setup()
|
||||
{
|
||||
// mScnMgr = scnMgr;
|
||||
// mDynWorld.reset(new Ogre::Bullet::DynamicsWorld(Ogre::Vector3(0, -9.8, 0)));
|
||||
// mDbgDraw.reset(new Ogre::Bullet::DebugDrawer(mScnMgr->getRootSceneNode(), mDynWorld->getBtWorld()));
|
||||
Ogre::MeshManager::getSingleton().createPlane(
|
||||
"floor",
|
||||
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||
Ogre::Plane(Ogre::Vector3::UNIT_Y, 0), 100, 100, 10, 10,
|
||||
true, 1, 10, 10, Ogre::Vector3::UNIT_Z);
|
||||
|
||||
// create a floor entity, give it a material, and place it at the origin
|
||||
Ogre::SceneManager *scnMgr =
|
||||
WorldData::get_singleton()->getSceneManager();
|
||||
Ogre::Entity *floor = scnMgr->createEntity("Floor", "floor");
|
||||
scnMgr->getRootSceneNode()->attachObject(floor);
|
||||
mFloorBody = WorldData::get_singleton()->addRigidBody(
|
||||
0, floor, Ogre::Bullet::CT_TRIMESH);
|
||||
}
|
||||
btRigidBody *addCharacter(Ogre::Entity *ent, float mass)
|
||||
{
|
||||
return WorldData::get_singleton()->addKinematicRigidBody(
|
||||
mass, ent, Ogre::Bullet::CT_COMPOUND);
|
||||
}
|
||||
bool frameStarted(const Ogre::FrameEvent &evt) override;
|
||||
};
|
||||
class CharacterController : public OgreBites::InputListener,
|
||||
Ogre::FrameListener {
|
||||
enum AnimID {
|
||||
ANIM_IDLE = 0,
|
||||
ANIM_WALK,
|
||||
ANIM_RUN,
|
||||
NUM_ANIMS,
|
||||
ANIM_NONE = NUM_ANIMS
|
||||
};
|
||||
Ogre::Node *mRootBone;
|
||||
Ogre::SceneNode *mCameraNode;
|
||||
Ogre::Camera *mCamera;
|
||||
Ogre::SceneManager *mScnMgr;
|
||||
|
||||
Ogre::SceneNode *mCameraPivot;
|
||||
Ogre::SceneNode *mCameraGoal, *mBodyNode;
|
||||
Ogre::Entity *mBodyEnt;
|
||||
Real mPivotPitch;
|
||||
Real mVerticalVelocity;
|
||||
Ogre::Vector3
|
||||
mKeyDirection; // player's local intended direction based on WASD keys
|
||||
Ogre::Vector3 mGoalDirection; // actual intended direction in world-space
|
||||
Ogre::AnimationState *mAnims[NUM_ANIMS]; // master animation list
|
||||
Ogre::Animation *mSkelAnimations[NUM_ANIMS];
|
||||
Ogre::NodeAnimationTrack *mHipsTracks[NUM_ANIMS];
|
||||
Ogre::NodeAnimationTrack *mRootTracks[NUM_ANIMS];
|
||||
AnimID mAnimID;
|
||||
bool mFadingIn[NUM_ANIMS]; // which animations are fading in
|
||||
bool mFadingOut[NUM_ANIMS]; // which animations are fading out
|
||||
Real mTimer; // general timer to see how long animations have been playing
|
||||
Ogre::Skeleton *mSkeleton;
|
||||
bool mRunning;
|
||||
MainWorld *world;
|
||||
Ogre::Vector3 rootMotion;
|
||||
Ogre::Quaternion rootRotation;
|
||||
// btRigidBody *mRigidBody;
|
||||
btCompoundShape *mCollisionShape;
|
||||
btPairCachingGhostObject *mGhostObject;
|
||||
btKinematicCharacterController *mController;
|
||||
|
||||
public:
|
||||
CharacterController(Ogre::SceneNode *camNode, Ogre::Camera *cam,
|
||||
Ogre::SceneManager *scnMgr, MainWorld *world);
|
||||
~CharacterController();
|
||||
|
||||
private:
|
||||
void setupBody();
|
||||
void setupCamera();
|
||||
void setupAnimations();
|
||||
|
||||
public:
|
||||
bool keyPressed(const OgreBites::KeyboardEvent &evt) override;
|
||||
bool keyReleased(const OgreBites::KeyboardEvent &evt) override;
|
||||
bool mouseMoved(const OgreBites::MouseMotionEvent &evt) override;
|
||||
bool mouseWheelRolled(const OgreBites::MouseWheelEvent &evt) override;
|
||||
bool mousePressed(const OgreBites::MouseButtonEvent &evt) override;
|
||||
bool frameStarted(const Ogre::FrameEvent &evt) override;
|
||||
void frameRendered(const Ogre::FrameEvent &evt) override;
|
||||
|
||||
private:
|
||||
void updateBody(Ogre::Real deltaTime);
|
||||
void updateAnimations(Real deltaTime);
|
||||
void updateRootMotion(Real deltaTime);
|
||||
void fadeAnimations(Real deltaTime);
|
||||
void updateCamera(Real deltaTime);
|
||||
void updateCameraGoal(Real deltaYaw, Real deltaPitch, Real deltaZoom);
|
||||
void setAnimation(AnimID id, bool reset = false);
|
||||
#if 0
|
||||
struct testMotionResult {
|
||||
};
|
||||
struct recoverResult {
|
||||
};
|
||||
|
||||
bool bodyTestMotion(btRigidBody *body,
|
||||
const btTransform &from,
|
||||
const btVector3 &motion, bool infinite_inertia,
|
||||
textMotionResult *result,
|
||||
bool excludeRaycastShapes,
|
||||
const std::set<btCollisionObject *> &exclude);
|
||||
bool recoverFromPenetration(btRigidBody *body,
|
||||
const btTransform &body_position,
|
||||
btScalar recover_movement_scale,
|
||||
bool infinite_inertia,
|
||||
btVector3 &delta_recover_movement,
|
||||
recoverResult *recover_result,
|
||||
const std::set<btCollisionObject *> &exclude);
|
||||
#endif
|
||||
inline btQuaternion convert(const Ogre::Quaternion &q)
|
||||
{
|
||||
return btQuaternion(q.x, q.y, q.z, q.w);
|
||||
}
|
||||
inline btVector3 convert(const Ogre::Vector3 &v)
|
||||
{
|
||||
return btVector3(v.x, v.y, v.z);
|
||||
}
|
||||
inline btTransform convert(const Ogre::Quaternion &q,
|
||||
const Ogre::Vector3 &v)
|
||||
{
|
||||
btQuaternion mq = convert(q);
|
||||
btVector3 mv = convert(v);
|
||||
return btTransform(mq, mv);
|
||||
}
|
||||
inline Ogre::Quaternion convert(const btQuaternion &q)
|
||||
{
|
||||
return Ogre::Quaternion(q.w(), q.x(), q.y(), q.z());
|
||||
}
|
||||
inline Ogre::Vector3 convert(const btVector3 &v)
|
||||
{
|
||||
return Ogre::Vector3(v.x(), v.y(), v.z());
|
||||
}
|
||||
inline void convert(const btTransform &from, Ogre::Quaternion &q,
|
||||
Ogre::Vector3 &v)
|
||||
{
|
||||
q = convert(from.getRotation());
|
||||
v = convert(from.getOrigin());
|
||||
}
|
||||
};
|
||||
CharacterController::CharacterController(Ogre::SceneNode *camNode,
|
||||
Ogre::Camera *cam,
|
||||
Ogre::SceneManager *scnMgr,
|
||||
MainWorld *world)
|
||||
: mCameraNode(camNode)
|
||||
, mCamera(cam)
|
||||
, mScnMgr(scnMgr)
|
||||
, mPivotPitch(0)
|
||||
, mVerticalVelocity(0)
|
||||
, mAnimID(ANIM_NONE)
|
||||
, mRunning(false)
|
||||
, world(world)
|
||||
, mCollisionShape(nullptr)
|
||||
, mGhostObject(nullptr)
|
||||
, mController(nullptr)
|
||||
{
|
||||
setupBody();
|
||||
setupCamera();
|
||||
setupAnimations();
|
||||
}
|
||||
CharacterController::~CharacterController()
|
||||
{
|
||||
}
|
||||
void CharacterController::setupBody()
|
||||
{
|
||||
mBodyEnt = mScnMgr->createEntity("normal-male.glb");
|
||||
mBodyNode = mScnMgr->getRootSceneNode()->createChildSceneNode();
|
||||
mBodyNode->attachObject(mBodyEnt);
|
||||
mSkeleton = mBodyEnt->getSkeleton();
|
||||
// mRigidBody = world->addCharacter(mBodyEnt, 0);
|
||||
// mCollisionShape = static_cast<btCompoundShape *>(mRigidBody->getCollisionShape());
|
||||
mGhostObject = new btPairCachingGhostObject();
|
||||
mCollisionShape = new btCompoundShape;
|
||||
mGhostObject->setCollisionShape(mCollisionShape);
|
||||
|
||||
{
|
||||
btVector3 inertia(0, 0, 0);
|
||||
// mCollisionShape = new btCompoundShape();
|
||||
btScalar height = 1.0f;
|
||||
btScalar radius = 0.3f;
|
||||
btCapsuleShape *shape =
|
||||
new btCapsuleShape(radius, 2 * height - 2 * radius);
|
||||
btTransform transform;
|
||||
transform.setIdentity();
|
||||
transform.setOrigin(btVector3(0, 1, 0));
|
||||
static_cast<btCompoundShape *>(mCollisionShape)
|
||||
->addChildShape(transform, shape);
|
||||
btScalar masses[1] = { 0 };
|
||||
btTransform principal;
|
||||
static_cast<btCompoundShape *>(mCollisionShape)
|
||||
->calculatePrincipalAxisTransform(masses, principal,
|
||||
inertia);
|
||||
}
|
||||
mGhostObject->setCollisionFlags(
|
||||
btCollisionObject::CF_KINEMATIC_OBJECT |
|
||||
btCollisionObject::CF_NO_CONTACT_RESPONSE);
|
||||
mGhostObject->setActivationState(DISABLE_DEACTIVATION);
|
||||
Ogre::Bullet::KinematicMotionSimple *controller =
|
||||
new Ogre::Bullet::KinematicMotionSimple(mGhostObject,
|
||||
mBodyNode);
|
||||
WorldData::get_singleton()->getWorld()->attachCollisionObject(
|
||||
mGhostObject, mBodyEnt, btBroadphaseProxy::AllFilter,
|
||||
btBroadphaseProxy::AllFilter);
|
||||
WorldData::get_singleton()->getBtWorld()->addAction(controller);
|
||||
|
||||
assert(mCollisionShape);
|
||||
#if 0
|
||||
if (mRigidBody->getMass() == 0) {
|
||||
#if 0
|
||||
mRigidBody->setCollisionFlags(mRigidBody->getCollisionFlags()
|
||||
| btCollisionObject::CF_KINEMATIC_OBJECT
|
||||
| btCollisionObject::CF_NO_CONTACT_RESPONSE
|
||||
);
|
||||
#endif
|
||||
#if 0
|
||||
mGhostObject->setWorldTransform(mRigidBody->getWorldTransform());
|
||||
WorldData::get_singleton()->getBtWorld()
|
||||
->getBroadphase()->getOverlappingPairCache()
|
||||
->setInternalGhostPairCallback(new btGhostPairCallback());
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
mRigidBody->setActivationState(DISABLE_DEACTIVATION);
|
||||
#endif
|
||||
#if 0
|
||||
{
|
||||
Ogre::Entity *e2 = mScnMgr->createEntity("normal-male.glb");
|
||||
Ogre::SceneNode *e2node = mScnMgr->getRootSceneNode()->createChildSceneNode();
|
||||
e2node->attachObject(e2);
|
||||
mGhostObject = WorldData::get_singleton()->addGhostObject(e2, mCollisionShape);
|
||||
mController = new btKinematicCharacterController(mGhostObject, mCollisionShape, 0.5f);
|
||||
WorldData::get_singleton()->getBtWorld()->addAction(mController);
|
||||
}
|
||||
#endif
|
||||
assert(mSkeleton->hasBone("Root"));
|
||||
mRootBone = mSkeleton->getBone("Root");
|
||||
assert(mRootBone);
|
||||
}
|
||||
void CharacterController::setupCamera()
|
||||
{
|
||||
// create a pivot at roughly the character's shoulder
|
||||
mCameraPivot = mScnMgr->getRootSceneNode()->createChildSceneNode();
|
||||
mCameraGoal =
|
||||
mCameraPivot->createChildSceneNode(Ogre::Vector3(0, 2, 3));
|
||||
mCameraNode->setPosition(mCameraPivot->getPosition() +
|
||||
mCameraGoal->getPosition());
|
||||
mCameraPivot->setFixedYawAxis(true);
|
||||
mCameraGoal->setFixedYawAxis(true);
|
||||
mCameraNode->setFixedYawAxis(true);
|
||||
// our model is quite small, so reduce the clipping planes
|
||||
mCamera->setNearClipDistance(0.1f);
|
||||
mCamera->setFarClipDistance(700);
|
||||
|
||||
mPivotPitch = 0;
|
||||
mKeyDirection = Ogre::Vector3::ZERO;
|
||||
mVerticalVelocity = 0;
|
||||
}
|
||||
void CharacterController::setupAnimations()
|
||||
{
|
||||
int i, j;
|
||||
mSkeleton->setBlendMode(Ogre::ANIMBLEND_CUMULATIVE);
|
||||
Ogre::String animNames[NUM_ANIMS] = { "idle", "walking", "running" };
|
||||
for (i = 0; i < NUM_ANIMS; i++) {
|
||||
mAnims[i] = mBodyEnt->getAnimationState(animNames[i]);
|
||||
mAnims[i]->setLoop(true);
|
||||
mAnims[i]->setEnabled(true);
|
||||
mAnims[i]->setWeight(0);
|
||||
mFadingIn[i] = false;
|
||||
mFadingOut[i] = false;
|
||||
mSkelAnimations[i] = mSkeleton->getAnimation(animNames[i]);
|
||||
for (const auto &it : mSkelAnimations[i]->_getNodeTrackList()) {
|
||||
Ogre::NodeAnimationTrack *track = it.second;
|
||||
Ogre::String trackName =
|
||||
track->getAssociatedNode()->getName();
|
||||
if (trackName == "mixamorig:Hips") {
|
||||
mHipsTracks[i] = track;
|
||||
} else if (trackName == "Root") {
|
||||
mRootTracks[i] = track;
|
||||
// mRootTracks[i]->removeAllKeyFrames();
|
||||
}
|
||||
}
|
||||
Ogre::Vector3 delta = Ogre::Vector3::ZERO;
|
||||
Ogre::Vector3 motion = Ogre::Vector3::ZERO;
|
||||
for (j = 0; j < mRootTracks[i]->getNumKeyFrames(); j++) {
|
||||
Ogre::Vector3 trans = mRootTracks[i]
|
||||
->getNodeKeyFrame(j)
|
||||
->getTranslate();
|
||||
if (j == 0)
|
||||
delta = trans;
|
||||
else
|
||||
delta = trans - motion;
|
||||
mRootTracks[i]->getNodeKeyFrame(j)->setTranslate(delta);
|
||||
motion = trans;
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
for(i = 0; i < NUM_ANIMS - 1; i++) {
|
||||
// need to cache
|
||||
int j;
|
||||
Ogre::String animName = mAnims[i]->getAnimationName();
|
||||
Ogre::Animation *anim = mSkeleton->getAnimation(animName);
|
||||
Ogre::NodeAnimationTrack *hips_track = nullptr, *root_track = nullptr;
|
||||
Ogre::Node *root_node = nullptr;
|
||||
for (const auto& it : anim->_getNodeTrackList()) {
|
||||
Ogre::NodeAnimationTrack* track = it.second;
|
||||
Ogre::String trackName = track->getAssociatedNode()->getName();
|
||||
std::cout << animName << " track: " << trackName << "\n";
|
||||
if (trackName == "mixamorig:Hips")
|
||||
hips_track = track;
|
||||
else if (trackName == "Root") {
|
||||
root_track = track;
|
||||
root_node = track->getAssociatedNode();
|
||||
}
|
||||
}
|
||||
assert(false);
|
||||
root_track->removeAllKeyFrames();
|
||||
std::cout << hips_track << " " << root_track << "\n";
|
||||
std::cout << hips_track->getNumKeyFrames() << " " << root_track->getNumKeyFrames() << "\n";
|
||||
assert(hips_track && root_track);
|
||||
Ogre::Vector3 delta = Ogre::Vector3::ZERO;
|
||||
for(j = 0; j < hips_track->getNumKeyFrames(); j++) {
|
||||
float timePos = hips_track->getNodeKeyFrame(j)->getTime();
|
||||
Ogre::Vector3 trans = hips_track->getNodeKeyFrame(j)->getTranslate();
|
||||
Ogre::Vector3 hips_trans(0, 0, 0);
|
||||
Ogre::Vector3 root_trans(0, 0, 0);
|
||||
hips_track->getNodeKeyFrame(j)->setTranslate(hips_trans);
|
||||
Ogre::TransformKeyFrame *nk = root_track->createNodeKeyFrame(timePos);
|
||||
nk->setTranslate(root_trans - delta);
|
||||
nk->setScale(Ogre::Vector3(1, 1, 1));
|
||||
nk->setRotation(Ogre::Quaternion());
|
||||
std::cout << animName << " delta: " << j << " " << timePos << " " << root_trans - delta << "\n";
|
||||
delta = root_trans;
|
||||
}
|
||||
for(j = 0; j < root_track->getNumKeyFrames(); j++) {
|
||||
float timePos = hips_track->getNodeKeyFrame(j)->getTime();
|
||||
Ogre::Vector3 root_trans = hips_track->getNodeKeyFrame(j)->getTranslate();
|
||||
std::cout << animName << " delta: root: " << j << " " << timePos << " " << root_trans << "\n";
|
||||
}
|
||||
}
|
||||
// assert(false);
|
||||
#endif
|
||||
setAnimation(ANIM_IDLE);
|
||||
}
|
||||
bool CharacterController::keyPressed(const OgreBites::KeyboardEvent &evt)
|
||||
{
|
||||
OgreBites::Keycode key = evt.keysym.sym;
|
||||
if (key == 'q' && (mAnimID == ANIM_IDLE)) {
|
||||
/* ... */
|
||||
mTimer = 0;
|
||||
} else if (key == 'e') {
|
||||
} else if (key == 'w')
|
||||
mKeyDirection.z = -1;
|
||||
else if (key == 'a')
|
||||
mKeyDirection.x = -1;
|
||||
else if (key == 's')
|
||||
mKeyDirection.z = 1;
|
||||
else if (key == 'd')
|
||||
mKeyDirection.x = 1;
|
||||
if (key == OgreBites::SDLK_LSHIFT)
|
||||
mRunning = true;
|
||||
if (!mKeyDirection.isZeroLength() && mAnimID == ANIM_IDLE) {
|
||||
if (mRunning)
|
||||
setAnimation(ANIM_RUN, true);
|
||||
else
|
||||
setAnimation(ANIM_WALK, true);
|
||||
// std::cout << "Walking\n";
|
||||
} else if (!mKeyDirection.isZeroLength() && mAnimID == ANIM_WALK &&
|
||||
mRunning)
|
||||
setAnimation(ANIM_RUN);
|
||||
return true;
|
||||
}
|
||||
bool CharacterController::keyReleased(const OgreBites::KeyboardEvent &evt)
|
||||
{
|
||||
OgreBites::Keycode key = evt.keysym.sym;
|
||||
if (key == 'w' && mKeyDirection.z == -1)
|
||||
mKeyDirection.z = 0;
|
||||
else if (key == 'a' && mKeyDirection.x == -1)
|
||||
mKeyDirection.x = 0;
|
||||
else if (key == 's' && mKeyDirection.z == 1)
|
||||
mKeyDirection.z = 0;
|
||||
else if (key == 'd' && mKeyDirection.x == 1)
|
||||
mKeyDirection.x = 0;
|
||||
if (key == OgreBites::SDLK_LSHIFT)
|
||||
mRunning = false;
|
||||
|
||||
if (mKeyDirection.isZeroLength() &&
|
||||
(mAnimID == ANIM_WALK || mAnimID == ANIM_RUN))
|
||||
setAnimation(ANIM_IDLE);
|
||||
else if (!mKeyDirection.isZeroLength() && mAnimID == ANIM_RUN &&
|
||||
!mRunning)
|
||||
setAnimation(ANIM_WALK);
|
||||
|
||||
return true;
|
||||
}
|
||||
bool CharacterController::mouseMoved(const OgreBites::MouseMotionEvent &evt)
|
||||
{
|
||||
// update camera goal based on mouse movement
|
||||
updateCameraGoal(-0.18f * evt.xrel, -0.12f * evt.yrel, 0);
|
||||
return true;
|
||||
}
|
||||
bool CharacterController::mouseWheelRolled(const OgreBites::MouseWheelEvent &evt)
|
||||
{
|
||||
// update camera goal based on mouse movement
|
||||
updateCameraGoal(0, 0, -0.15f * evt.y);
|
||||
return true;
|
||||
}
|
||||
bool CharacterController::mousePressed(const OgreBites::MouseButtonEvent &evt)
|
||||
{
|
||||
std::cout << "Mouse press\n";
|
||||
return false;
|
||||
}
|
||||
void CharacterController::frameRendered(const Ogre::FrameEvent &evt)
|
||||
{
|
||||
updateBody(evt.timeSinceLastFrame);
|
||||
updateAnimations(evt.timeSinceLastFrame);
|
||||
updateCamera(evt.timeSinceLastFrame);
|
||||
if (evt.timeSinceLastFrame > 0)
|
||||
updateRootMotion(evt.timeSinceLastFrame);
|
||||
}
|
||||
bool CharacterController::frameStarted(const Ogre::FrameEvent &evt)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
void CharacterController::updateCameraGoal(Real deltaYaw, Real deltaPitch,
|
||||
Real deltaZoom)
|
||||
{
|
||||
mCameraPivot->yaw(Ogre::Degree(deltaYaw), Ogre::Node::TS_PARENT);
|
||||
if (!(mPivotPitch + deltaPitch > 25 && deltaPitch > 0) &&
|
||||
!(mPivotPitch + deltaPitch < -60 && deltaPitch < 0)) {
|
||||
mCameraPivot->pitch(Ogre::Degree(deltaPitch),
|
||||
Ogre::Node::TS_LOCAL);
|
||||
mPivotPitch += deltaPitch;
|
||||
}
|
||||
Real dist = mCameraGoal->_getDerivedPosition().distance(
|
||||
mCameraPivot->_getDerivedPosition());
|
||||
Real distChange = deltaZoom * dist;
|
||||
|
||||
// bound the zoom
|
||||
if (!(dist + distChange < 8 && distChange < 0) &&
|
||||
!(dist + distChange > 25 && distChange > 0))
|
||||
mCameraGoal->translate(0, 0, distChange, Ogre::Node::TS_LOCAL);
|
||||
}
|
||||
void CharacterController::updateBody(Real delta)
|
||||
{
|
||||
mGoalDirection = Ogre::Vector3::ZERO;
|
||||
if (mKeyDirection != Ogre::Vector3::ZERO) {
|
||||
// calculate actually goal direction in world based on player's key directions
|
||||
mGoalDirection +=
|
||||
mKeyDirection.z * mCameraNode->getOrientation().zAxis();
|
||||
mGoalDirection +=
|
||||
mKeyDirection.x * mCameraNode->getOrientation().xAxis();
|
||||
mGoalDirection.y = 0;
|
||||
mGoalDirection.normalise();
|
||||
|
||||
Ogre::Quaternion toGoal =
|
||||
mBodyNode->getOrientation().zAxis().getRotationTo(
|
||||
mGoalDirection);
|
||||
// calculate how much the character has to turn to face goal direction
|
||||
Real yawToGoal = toGoal.getYaw().valueDegrees();
|
||||
// this is how much the character CAN turn this frame
|
||||
Real yawAtSpeed =
|
||||
yawToGoal / Math::Abs(yawToGoal) * delta * TURN_SPEED;
|
||||
// reduce "turnability" if we're in midair
|
||||
// if (mBaseAnimID == ANIM_JUMP_LOOP) yawAtSpeed *= 0.2f;
|
||||
if (yawToGoal < 0)
|
||||
yawToGoal = std::min<Real>(
|
||||
0,
|
||||
std::max<Real>(
|
||||
yawToGoal,
|
||||
yawAtSpeed)); //yawToGoal = Math::Clamp<Real>(yawToGoal, yawAtSpeed, 0);
|
||||
else if (yawToGoal > 0)
|
||||
yawToGoal = std::max<Real>(
|
||||
0,
|
||||
std::min<Real>(
|
||||
yawToGoal,
|
||||
yawAtSpeed)); //yawToGoal = Math::Clamp<Real>(yawToGoal, 0, yawAtSpeed);
|
||||
mBodyNode->yaw(Ogre::Degree(yawToGoal));
|
||||
// move in current body direction (not the goal direction)
|
||||
// mBodyNode->translate(0, 0, delta * RUN_SPEED * mAnims[mAnimID]->getWeight(),
|
||||
// Ogre::Node::TS_LOCAL);
|
||||
#if 0
|
||||
if (mBaseAnimID == ANIM_JUMP_LOOP)
|
||||
{
|
||||
// if we're jumping, add a vertical offset too, and apply gravity
|
||||
mBodyNode->translate(0, mVerticalVelocity * deltaTime, 0, Node::TS_LOCAL);
|
||||
mVerticalVelocity -= GRAVITY * deltaTime;
|
||||
|
||||
Vector3 pos = mBodyNode->getPosition();
|
||||
if (pos.y <= CHAR_HEIGHT)
|
||||
{
|
||||
// if we've hit the ground, change to landing state
|
||||
pos.y = CHAR_HEIGHT;
|
||||
mBodyNode->setPosition(pos);
|
||||
setBaseAnimation(ANIM_JUMP_END, true);
|
||||
mTimer = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
void CharacterController::updateAnimations(Real delta)
|
||||
{
|
||||
int i, j, k;
|
||||
Real animSpeed = 1;
|
||||
mTimer += delta;
|
||||
if (mAnimID != ANIM_NONE) {
|
||||
if (mAnimID == ANIM_WALK)
|
||||
mAnims[mAnimID]->addTime(delta * 1.0f);
|
||||
else
|
||||
mAnims[mAnimID]->addTime(delta * animSpeed);
|
||||
}
|
||||
fadeAnimations(delta);
|
||||
}
|
||||
void CharacterController::updateRootMotion(Real delta)
|
||||
{
|
||||
Ogre::Vector3 boneMotion = mRootBone->getPosition();
|
||||
OgreAssert(delta > 0.0f, "Zero delta");
|
||||
#if 0
|
||||
Ogre::Vector3 motion = boneMotion - rootMotion;
|
||||
if (motion.squaredLength() > 0.1f * 0.1f)
|
||||
motion = Ogre::Vector3();
|
||||
rootMotion = boneMotion;
|
||||
#endif
|
||||
#if 0
|
||||
float mass = mRigidBody->getMass();
|
||||
std::cout << "Root bone position: " << boneMotion << "\n";
|
||||
std::cout << "body mass: " << mass << "\n";
|
||||
#endif
|
||||
/* Kinematic motion */
|
||||
Ogre::Quaternion rot = mBodyNode->getOrientation();
|
||||
Ogre::Vector3 gravity(0, -9.8, 0);
|
||||
Ogre::Vector3 velocity = rot * boneMotion / delta;
|
||||
velocity += gravity * delta;
|
||||
Ogre::Vector3 rotMotion = velocity * delta;
|
||||
btTransform from(convert(mBodyNode->getOrientation()),
|
||||
convert(mBodyNode->getPosition()));
|
||||
mBodyNode->setPosition(mBodyNode->getPosition() + rotMotion);
|
||||
// WorldData::get_singleton()->getWorld()->testBodyMotion(mRigidBody, from, Ogre::Bullet::convert(rotMotion), true,
|
||||
// nullptr, false, std::set<btCollisionObject *>());
|
||||
}
|
||||
void CharacterController::fadeAnimations(Real delta)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < NUM_ANIMS; i++) {
|
||||
if (mFadingIn[i]) {
|
||||
// slowly fade this animation in until it has full weight
|
||||
Real newWeight = mAnims[i]->getWeight() +
|
||||
delta * ANIM_FADE_SPEED;
|
||||
mAnims[i]->setWeight(
|
||||
Math::Clamp<Real>(newWeight, 0, 1));
|
||||
if (newWeight >= 1)
|
||||
mFadingIn[i] = false;
|
||||
} else if (mFadingOut[i]) {
|
||||
// slowly fade this animation out until it has no weight, and then disable it
|
||||
Real newWeight = mAnims[i]->getWeight() -
|
||||
delta * ANIM_FADE_SPEED;
|
||||
mAnims[i]->setWeight(
|
||||
Math::Clamp<Real>(newWeight, 0, 1));
|
||||
if (newWeight <= 0) {
|
||||
mAnims[i]->setEnabled(false);
|
||||
mFadingOut[i] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void CharacterController::updateCamera(Real delta)
|
||||
{
|
||||
// place the camera pivot roughly at the character's shoulder
|
||||
mCameraPivot->setPosition(mBodyNode->getPosition() +
|
||||
Ogre::Vector3::UNIT_Y * CAM_HEIGHT);
|
||||
// move the camera smoothly to the goal
|
||||
Ogre::Vector3 goalOffset =
|
||||
mCameraGoal->_getDerivedPosition() - mCameraNode->getPosition();
|
||||
mCameraNode->translate(goalOffset * delta * 9.0f);
|
||||
// always look at the pivot
|
||||
mCameraNode->lookAt(mCameraPivot->_getDerivedPosition(),
|
||||
Ogre::Node::TS_PARENT);
|
||||
}
|
||||
void CharacterController::setAnimation(AnimID id, bool reset)
|
||||
{
|
||||
assert(id >= 0 && id < NUM_ANIMS);
|
||||
if (mAnimID != ANIM_NONE) {
|
||||
mFadingIn[mAnimID] = false;
|
||||
mFadingOut[mAnimID] = true;
|
||||
}
|
||||
mAnimID = id;
|
||||
if (id != ANIM_NONE) {
|
||||
mAnims[id]->setEnabled(true);
|
||||
mAnims[id]->setWeight(0);
|
||||
mFadingOut[id] = false;
|
||||
mFadingIn[id] = true;
|
||||
if (reset)
|
||||
mAnims[id]->setTimePosition(0);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
bool CharacterController::recoverFromPenetration(btRigidBody *body,
|
||||
const btTransform &body_position,
|
||||
btScalar recover_movement_scale,
|
||||
bool infinite_inertia,
|
||||
btVector3 &delta_recover_movement,
|
||||
recoverResult *recover_result,
|
||||
const std::set<btCollisionObject *> &exclude)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CharacterController::bodyTestMotion(btRigidBody *body,
|
||||
const btTransform &from,
|
||||
const btVector3 &motion, bool infinite_inertia,
|
||||
textMotionResult *result,
|
||||
bool excludeRaycastShapes,
|
||||
std::set<btCollisionObject *> exclude)
|
||||
{
|
||||
int t;
|
||||
btTransform body_transform;
|
||||
btVector3 initial_recover_motion(0, 0, 0);
|
||||
// phase one - depenetration
|
||||
for (t = 0; t < RECOVERING_MOVEMENT_CYCLES; t++)
|
||||
if (!recoverFromPenetration(body,
|
||||
body_transform,
|
||||
RECOVERING_MOVEMENT_SCALE,
|
||||
infinite_inertia,
|
||||
initial_recover_motion,
|
||||
nullptr, exclude))
|
||||
break;
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
class KeyHandler : public OgreBites::InputListener {
|
||||
bool keyPressed(const OgreBites::KeyboardEvent &evt) override
|
||||
{
|
||||
if (evt.keysym.sym == OgreBites::SDLK_ESCAPE) {
|
||||
Ogre::Root::getSingleton().queueEndRendering();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
bool MainWorld::frameStarted(const Ogre::FrameEvent &evt)
|
||||
{
|
||||
WorldData::get_singleton()->update(evt.timeSinceLastFrame);
|
||||
return true;
|
||||
}
|
||||
class App : public OgreBites::ApplicationContext {
|
||||
Ogre::SceneNode *mCameraNode;
|
||||
Ogre::SceneManager *mScnMgr;
|
||||
std::unique_ptr<CharacterController> mCharacter;
|
||||
KeyHandler mKeyHandler;
|
||||
MainWorld mWorld;
|
||||
|
||||
public:
|
||||
App();
|
||||
virtual ~App();
|
||||
|
||||
void setup();
|
||||
void locateResources();
|
||||
void initCamera();
|
||||
Ogre::SceneManager *getSceneManager()
|
||||
{
|
||||
return mScnMgr;
|
||||
}
|
||||
void createContent();
|
||||
void createCharacter();
|
||||
void setupWorld();
|
||||
};
|
||||
|
||||
App::App()
|
||||
: OgreBites::ApplicationContext("App")
|
||||
{
|
||||
}
|
||||
void App::setup()
|
||||
{
|
||||
OgreBites::ApplicationContext::setup();
|
||||
Ogre::Root *root = getRoot();
|
||||
Ogre::SceneManager *scnMgr = root->createSceneManager();
|
||||
mScnMgr = scnMgr;
|
||||
}
|
||||
void App::locateResources()
|
||||
{
|
||||
OgreBites::ApplicationContext::locateResources();
|
||||
}
|
||||
App::~App()
|
||||
{
|
||||
}
|
||||
void App::initCamera()
|
||||
{
|
||||
// also need to tell where we are
|
||||
mCameraNode = mScnMgr->getRootSceneNode()->createChildSceneNode();
|
||||
mCameraNode->setPosition(0, 2, 3);
|
||||
mCameraNode->lookAt(Ogre::Vector3(0, 1, -1), Ogre::Node::TS_PARENT);
|
||||
|
||||
// create the camera
|
||||
Ogre::Camera *cam = mScnMgr->createCamera("tps_camera");
|
||||
cam->setNearClipDistance(0.1f); // specific to this sample
|
||||
cam->setAutoAspectRatio(true);
|
||||
mCameraNode->attachObject(cam);
|
||||
|
||||
// and tell it to render into the main window
|
||||
getRenderWindow()->addViewport(cam);
|
||||
}
|
||||
void App::setupWorld()
|
||||
{
|
||||
addInputListener(&mKeyHandler);
|
||||
mWorld.setup();
|
||||
getRoot()->addFrameListener(&mWorld);
|
||||
}
|
||||
void App::createCharacter()
|
||||
{
|
||||
Ogre::Camera *cam = static_cast<Ogre::Camera *>(
|
||||
mCameraNode->getAttachedObject("tps_camera"));
|
||||
mCharacter = std::make_unique<CharacterController>(mCameraNode, cam,
|
||||
mScnMgr, &mWorld);
|
||||
// mInputListenerChain = TouchAgnosticInputListenerChain(getRenderWindow(), {&mKeyHandler, mCharacter.get()});
|
||||
addInputListener(mCharacter.get());
|
||||
WorldData::get_singleton()->initPagedWorld(cam);
|
||||
}
|
||||
void App::createContent()
|
||||
{
|
||||
// without light we would just get a black screen
|
||||
Ogre::Light *light = mScnMgr->createLight("MainLight");
|
||||
Ogre::SceneNode *lightNode =
|
||||
mScnMgr->getRootSceneNode()->createChildSceneNode();
|
||||
// lightNode->setPosition(0, 10, 15);
|
||||
lightNode->setDirection(
|
||||
Ogre::Vector3(0.55, -0.3, 0.75).normalisedCopy());
|
||||
lightNode->attachObject(light);
|
||||
light->setType(Ogre::Light::LT_DIRECTIONAL);
|
||||
light->setDiffuseColour(Ogre::ColourValue::White);
|
||||
light->setSpecularColour(Ogre::ColourValue(0.4, 0.4, 0.4));
|
||||
mScnMgr->setSkyBox(true, "Skybox", 490);
|
||||
// Two boxes in one batch
|
||||
Procedural::TriangleBuffer tb;
|
||||
Procedural::BoxGenerator b;
|
||||
b.setPosition(2, 0, 0).addToTriangleBuffer(tb);
|
||||
b.setPosition(-2, 0, 0).addToTriangleBuffer(tb);
|
||||
tb.transformToMesh("twoBoxes");
|
||||
Ogre::Entity *ent = mScnMgr->createEntity("twoBoxes");
|
||||
Ogre::SceneNode *boxes =
|
||||
mScnMgr->getRootSceneNode()->createChildSceneNode(
|
||||
"boxes", Ogre::Vector3(5, 0, -5));
|
||||
boxes->attachObject(ent);
|
||||
}
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
App ctx;
|
||||
ctx.initApp();
|
||||
// get a pointer to the already created root
|
||||
Ogre::Root *root = ctx.getRoot();
|
||||
Ogre::SceneManager *scnMgr = ctx.getSceneManager();
|
||||
|
||||
// register our scene with the RTSS
|
||||
Ogre::RTShader::ShaderGenerator *shadergen =
|
||||
Ogre::RTShader::ShaderGenerator::getSingletonPtr();
|
||||
shadergen->addSceneManager(scnMgr);
|
||||
WorldData::init(root, scnMgr);
|
||||
ctx.setWindowGrab(true);
|
||||
ctx.createContent();
|
||||
ctx.initCamera();
|
||||
ctx.setupWorld();
|
||||
ctx.createCharacter();
|
||||
// register for input events
|
||||
// KeyHandler keyHandler;
|
||||
// ctx.addInputListener(&keyHandler);
|
||||
|
||||
ctx.getRoot()->startRendering();
|
||||
ctx.setWindowGrab(false);
|
||||
ctx.closeApp();
|
||||
WorldData::cleanup();
|
||||
return 0;
|
||||
}
|
||||
39
lua-scripts/data.lua
Normal file
@@ -0,0 +1,39 @@
|
||||
function foo()
|
||||
tree()
|
||||
.node("p1", Quaternion(), Vector3(0, 0, -200))
|
||||
.entity("b1", "residental-house1.glb")
|
||||
.endnode()
|
||||
.node("p2", Quaternion(), Vector3(0, 0, -150))
|
||||
.entity("residental-house1.glb")
|
||||
.endnode()
|
||||
.node("p3", Quaternion(), Vector3(0, 0, -100))
|
||||
.entity("residental-house1.glb")
|
||||
.endnode()
|
||||
.node("p4", Quaternion(), Vector3(0, 0, -50))
|
||||
.entity("residental-house1.glb")
|
||||
.endnode()
|
||||
.node("p5", Quaternion(), Vector3(0, 0, 50))
|
||||
.entity("residental-house1.glb")
|
||||
.endnode()
|
||||
.node("p6", Quaternion(), Vector3(0, 0, 100))
|
||||
.entity("residental-house1.glb")
|
||||
.endnode()
|
||||
.node("p7", Quaternion(), Vector3(0, 0, 150))
|
||||
.entity("residental-house2.glb")
|
||||
.endnode()
|
||||
.node("p8", Quaternion(), Vector3(0, 0, 200))
|
||||
.entity("residental-house3.glb")
|
||||
.endnode()
|
||||
for x = -1000, 1000, 50 do
|
||||
for z = -1000, 1000, 50 do
|
||||
if not ((x >-100 and x < 100) and (z > -100 and z < 100)) then
|
||||
tree()
|
||||
.node("p00" .. tostring(x * 1000 + z), Quaternion(), Vector3(x, 0, z))
|
||||
.entity("residental-house2.glb")
|
||||
.endnode()
|
||||
end
|
||||
end
|
||||
end
|
||||
v = Vector3(0, 1, 2)
|
||||
end
|
||||
foo()
|
||||
@@ -18,6 +18,9 @@ FileSystem=resources/terrain
|
||||
# Rarely used resources should be separately loaded by the
|
||||
# samples which require them.
|
||||
[General]
|
||||
FileSystem=skybox
|
||||
FileSystem=resources/buildings
|
||||
FileSystem=resources/debug
|
||||
# PBR media must come before the scripts that reference it
|
||||
#FileSystem=./Media/PBR
|
||||
#FileSystem=./Media/PBR/filament
|
||||
@@ -63,6 +66,8 @@ FileSystem=resources/terrain
|
||||
# Materials for visual tests
|
||||
#[Tests]
|
||||
#FileSystem=/media/slapin/library/ogre/ogre-sdk/Tests/Media
|
||||
[LuaScripts]
|
||||
FileSystem=lua-scripts
|
||||
|
||||
[Characters]
|
||||
FileSystem=./characters/male
|
||||
|
||||
11
resources/debug/debug.frag
Normal file
@@ -0,0 +1,11 @@
|
||||
OGRE_NATIVE_GLSL_VERSION_DIRECTIVE
|
||||
#include <OgreUnifiedShader.h>
|
||||
|
||||
OGRE_UNIFORMS(uniform vec4 ambient;)
|
||||
OGRE_UNIFORMS(uniform vec4 diffuse;)
|
||||
|
||||
MAIN_PARAMETERS
|
||||
MAIN_DECLARATION
|
||||
{
|
||||
gl_FragColor = ambient * diffuse;
|
||||
}
|
||||
71
resources/debug/debug.material
Normal file
@@ -0,0 +1,71 @@
|
||||
material Skybox/Debug1
|
||||
{
|
||||
technique
|
||||
{
|
||||
pass
|
||||
{
|
||||
lighting off
|
||||
depth_write off
|
||||
ambient 1.0 0.0 0.0 1.0
|
||||
diffuse 1.0 0.0 0.0 1.0
|
||||
vertex_program_ref debug_vp
|
||||
{
|
||||
}
|
||||
fragment_program_ref debug_fp
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
material Debug/Red
|
||||
{
|
||||
technique
|
||||
{
|
||||
pass
|
||||
{
|
||||
lighting off
|
||||
depth_check on
|
||||
depth_write on
|
||||
depth_func always_pass
|
||||
ambient 1.0 0.0 0.0 1.0
|
||||
diffuse vertexcolour
|
||||
specular 0.0 0.0 0.0 1.0
|
||||
cull_software none
|
||||
cull_hardware none
|
||||
/*
|
||||
rtshader_system
|
||||
{
|
||||
lighting_stage metal_roughness
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
material Debug/Red2
|
||||
{
|
||||
technique
|
||||
{
|
||||
pass
|
||||
{
|
||||
lighting off
|
||||
depth_check on
|
||||
depth_write on
|
||||
depth_func always_pass
|
||||
ambient 1.0 0.0 0.0 1.0
|
||||
diffuse vertexcolour
|
||||
specular 0.0 0.0 0.0 1.0
|
||||
cull_software none
|
||||
cull_hardware none
|
||||
|
||||
rtshader_system
|
||||
{
|
||||
lighting_stage metal_roughness
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
19
resources/debug/debug.program
Normal file
@@ -0,0 +1,19 @@
|
||||
fragment_program debug_fp glsl glsles glslang hlsl
|
||||
{
|
||||
source debug.frag
|
||||
default_params
|
||||
{
|
||||
param_named_auto ambient surface_ambient_colour
|
||||
param_named_auto diffuse surface_diffuse_colour
|
||||
}
|
||||
}
|
||||
|
||||
vertex_program debug_vp glsl glsles glslang hlsl
|
||||
{
|
||||
source debug.vert
|
||||
default_params
|
||||
{
|
||||
param_named worldViewProj worldviewproj_matrix
|
||||
}
|
||||
}
|
||||
|
||||
25
resources/debug/debug.vert
Normal file
@@ -0,0 +1,25 @@
|
||||
OGRE_NATIVE_GLSL_VERSION_DIRECTIVE
|
||||
#include <OgreUnifiedShader.h>
|
||||
|
||||
OGRE_UNIFORMS(
|
||||
uniform mat4 worldViewProj;
|
||||
)
|
||||
|
||||
MAIN_PARAMETERS
|
||||
IN(vec4 vertex, POSITION)
|
||||
IN(vec3 normal, NORMAL)
|
||||
IN(vec3 tangent, TANGENT)
|
||||
IN(vec3 uv0, TEXCOORD0)
|
||||
// uniform mat4 worldViewProj;
|
||||
|
||||
// attribute vec4 vertex;
|
||||
// attribute vec3 normal;
|
||||
// attribute vec4 tangent;
|
||||
// attribute vec2 uv0;
|
||||
|
||||
MAIN_DECLARATION
|
||||
// void main()
|
||||
{
|
||||
// gl_Position = mul(worldViewProj, position);
|
||||
gl_Position = worldViewProj * vertex;
|
||||
}
|
||||
38
resources/main/DefaultShaders.metal
Normal file
@@ -0,0 +1,38 @@
|
||||
#include "OgreUnifiedShader.h"
|
||||
|
||||
struct RasterizerData
|
||||
{
|
||||
vec4 pos [[position]];
|
||||
vec2 uv;
|
||||
};
|
||||
|
||||
struct Vertex
|
||||
{
|
||||
IN(vec3 pos, POSITION);
|
||||
IN(vec2 uv, TEXCOORD0);
|
||||
};
|
||||
|
||||
struct Uniform
|
||||
{
|
||||
mat4 mvpMtx;
|
||||
mat4 texMtx;
|
||||
};
|
||||
|
||||
// first 15 slots are reserved for the vertex attributes
|
||||
#define UNIFORM_INDEX_START 16
|
||||
|
||||
vertex RasterizerData default_vp(Vertex in [[stage_in]],
|
||||
constant Uniform& u [[buffer(UNIFORM_INDEX_START)]])
|
||||
{
|
||||
RasterizerData out;
|
||||
out.pos = u.mvpMtx * vec4(in.pos, 1);
|
||||
out.uv = (u.texMtx * vec4(in.uv,1,1)).xy;
|
||||
return out;
|
||||
}
|
||||
|
||||
fragment half4 default_fp(RasterizerData in [[stage_in]],
|
||||
metal::texture2d<half> tex [[texture(0)]],
|
||||
metal::sampler s [[sampler(0)]])
|
||||
{
|
||||
return tex.sample(s, in.uv);
|
||||
}
|
||||
97
resources/main/GLSL_GL3Support.glsl
Normal file
@@ -0,0 +1,97 @@
|
||||
// This file is part of the OGRE project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at https://www.ogre3d.org/licensing.
|
||||
|
||||
// @public-api
|
||||
|
||||
#if defined(OGRE_FRAGMENT_SHADER) && defined(OGRE_GLSLES)
|
||||
// define default precisions for ES fragement shaders
|
||||
precision mediump float;
|
||||
|
||||
#if __VERSION__ > 100
|
||||
precision lowp sampler2DArray;
|
||||
precision lowp sampler2DShadow;
|
||||
precision lowp sampler3D;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if __VERSION__ == 100
|
||||
mat2 transpose(mat2 m)
|
||||
{
|
||||
return mat2(m[0][0], m[1][0],
|
||||
m[0][1], m[1][1]);
|
||||
}
|
||||
|
||||
mat3 transpose(mat3 m)
|
||||
{
|
||||
return mat3(m[0][0], m[1][0], m[2][0],
|
||||
m[0][1], m[1][1], m[2][1],
|
||||
m[0][2], m[1][2], m[2][2]);
|
||||
}
|
||||
|
||||
mat4 transpose(mat4 m)
|
||||
{
|
||||
return mat4(m[0][0], m[1][0], m[2][0], m[3][0],
|
||||
m[0][1], m[1][1], m[2][1], m[3][1],
|
||||
m[0][2], m[1][2], m[2][2], m[3][2],
|
||||
m[0][3], m[1][3], m[2][3], m[3][3]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if __VERSION__ > 120 || defined(OGRE_GLSLANG)
|
||||
#define texture1D texture
|
||||
#define texture2D texture
|
||||
#define texture3D texture
|
||||
#define texture2DArray texture
|
||||
#define textureCube texture
|
||||
#define shadow2D texture
|
||||
#define shadow2DProj textureProj
|
||||
#define texture2DProj textureProj
|
||||
#define texture2DLod textureLod
|
||||
#define textureCubeLod textureLod
|
||||
|
||||
#if defined(OGRE_GLSLANG) || (__VERSION__ > 150 && defined(OGRE_VERTEX_SHADER)) || __VERSION__ >= 410
|
||||
#define IN(decl, loc) layout(location = loc) in decl;
|
||||
#else
|
||||
#define IN(decl, loc) in decl;
|
||||
#endif
|
||||
|
||||
#if defined(OGRE_GLSLANG) || (__VERSION__ > 150 && defined(OGRE_FRAGMENT_SHADER)) || __VERSION__ >= 410
|
||||
#define OUT(decl, loc) layout(location = loc) out decl;
|
||||
#else
|
||||
#define OUT(decl, loc) out decl;
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#ifdef OGRE_VERTEX_SHADER
|
||||
#define IN(decl, loc) attribute decl;
|
||||
#define OUT(decl, loc) varying decl;
|
||||
#else
|
||||
#define IN(decl, loc) varying decl;
|
||||
#define OUT(decl, loc) out decl;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(OGRE_FRAGMENT_SHADER) && (defined(OGRE_GLSLANG) || (__VERSION__ > 130))
|
||||
#define gl_FragColor FragColor
|
||||
OUT(vec4 FragColor, 0)
|
||||
#endif
|
||||
|
||||
#ifdef VULKAN
|
||||
|
||||
#ifdef OGRE_VERTEX_SHADER
|
||||
#define OGRE_UNIFORMS_BEGIN layout(binding = 0, row_major) uniform OgreUniforms {
|
||||
#else
|
||||
#define OGRE_UNIFORMS_BEGIN layout(binding = 1, row_major) uniform OgreUniforms {
|
||||
#endif
|
||||
|
||||
#define OGRE_UNIFORMS_END };
|
||||
|
||||
#else
|
||||
|
||||
#define OGRE_UNIFORMS_BEGIN
|
||||
#define OGRE_UNIFORMS_END
|
||||
|
||||
#endif
|
||||
98
resources/main/HLSL_SM4Support.hlsl
Normal file
@@ -0,0 +1,98 @@
|
||||
// This file is part of the OGRE project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at https://www.ogre3d.org/licensing.
|
||||
|
||||
// @public-api
|
||||
|
||||
#if OGRE_HLSL >= 4
|
||||
|
||||
// SM4 separates sampler into Texture and SamplerState
|
||||
|
||||
#define sampler1D Sampler1D
|
||||
#define sampler2D Sampler2D
|
||||
#define sampler3D Sampler3D
|
||||
#define samplerCUBE SamplerCube
|
||||
|
||||
struct Sampler1D
|
||||
{
|
||||
Texture1D t;
|
||||
SamplerState s;
|
||||
};
|
||||
struct Sampler2D
|
||||
{
|
||||
Texture2D t;
|
||||
SamplerState s;
|
||||
};
|
||||
struct Sampler3D
|
||||
{
|
||||
Texture3D t;
|
||||
SamplerState s;
|
||||
};
|
||||
struct SamplerCube
|
||||
{
|
||||
TextureCube t;
|
||||
SamplerState s;
|
||||
};
|
||||
|
||||
float4 tex1D(Sampler1D s, float v) { return s.t.Sample(s.s, v); }
|
||||
float4 tex2D(Sampler2D s, float2 v) { return s.t.Sample(s.s, v); }
|
||||
float4 tex3D(Sampler3D s, float3 v) { return s.t.Sample(s.s, v); }
|
||||
float4 texCUBE(SamplerCube s, float3 v) { return s.t.Sample(s.s, v); }
|
||||
float4 texCUBElod(SamplerCube s, float4 v) { return s.t.SampleLevel(s.s, v.xyz, v.w); }
|
||||
|
||||
float4 tex2D(Sampler2D s, float2 v, float2 ddx, float2 ddy) { return s.t.SampleGrad(s.s, v, ddx, ddy); }
|
||||
float4 tex2Dproj(Sampler2D s, float4 v) { return s.t.Sample(s.s, v.xy/v.w); }
|
||||
float4 tex2Dlod(Sampler2D s, float4 v) { return s.t.SampleLevel(s.s, v.xy, v.w); }
|
||||
|
||||
#define SAMPLER1D(name, reg) \
|
||||
Texture1D name ## Tex : register(t ## reg);\
|
||||
SamplerState name ## State : register(s ## reg);\
|
||||
static Sampler1D name = {name ## Tex, name ## State}
|
||||
|
||||
#define SAMPLER2D(name, reg) \
|
||||
Texture2D name ## Tex : register(t ## reg);\
|
||||
SamplerState name ## State : register(s ## reg);\
|
||||
static Sampler2D name = {name ## Tex, name ## State}
|
||||
|
||||
#define SAMPLER3D(name, reg) \
|
||||
Texture3D name ## Tex : register(t ## reg);\
|
||||
SamplerState name ## State : register(s ## reg);\
|
||||
static Sampler3D name = {name ## Tex, name ## State}
|
||||
|
||||
#define SAMPLERCUBE(name, reg) \
|
||||
TextureCube name ## Tex : register(t ## reg);\
|
||||
SamplerState name ## State : register(s ## reg);\
|
||||
static SamplerCube name = {name ## Tex, name ## State}
|
||||
|
||||
// the following are not available in D3D9, but provided for convenience
|
||||
struct Sampler2DShadow
|
||||
{
|
||||
Texture2D t;
|
||||
SamplerComparisonState s;
|
||||
};
|
||||
struct Sampler2DArray
|
||||
{
|
||||
Texture2DArray t;
|
||||
SamplerState s;
|
||||
};
|
||||
|
||||
#define SAMPLER2DSHADOW(name, reg) \
|
||||
Texture2D name ## Tex : register(t ## reg);\
|
||||
SamplerComparisonState name ## State : register(s ## reg);\
|
||||
static Sampler2DShadow name = {name ## Tex, name ## State}
|
||||
|
||||
#define SAMPLER2DARRAY(name, reg) \
|
||||
Texture2DArray name ## Tex : register(t ## reg);\
|
||||
SamplerState name ## State : register(s ## reg);\
|
||||
static Sampler2DArray name = {name ## Tex, name ## State}
|
||||
|
||||
float tex2Dcmp(Sampler2DShadow s, float3 v) { return s.t.SampleCmpLevelZero(s.s, v.xy, v.z); }
|
||||
float4 tex2DARRAY(Sampler2DArray s, float3 v) { return s.t.Sample(s.s, v); }
|
||||
#else
|
||||
|
||||
#define SAMPLER1D(name, reg) sampler1D name : register(s ## reg)
|
||||
#define SAMPLER2D(name, reg) sampler2D name : register(s ## reg)
|
||||
#define SAMPLER3D(name, reg) sampler3D name : register(s ## reg)
|
||||
#define SAMPLERCUBE(name, reg) samplerCUBE name : register(s ## reg)
|
||||
|
||||
#endif
|
||||
185
resources/main/OgreUnifiedShader.h
Normal file
@@ -0,0 +1,185 @@
|
||||
// This file is part of the OGRE project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at https://www.ogre3d.org/licensing.
|
||||
|
||||
// greatly inspired by
|
||||
// - shiny: https://ogrecave.github.io/shiny/defining-materials-shaders.html
|
||||
// - bgfx: https://github.com/bkaradzic/bgfx/blob/master/src/bgfx_shader.sh
|
||||
|
||||
/// general usage:
|
||||
// MAIN_PARAMETERS
|
||||
// IN(vec4 vertex, POSITION)
|
||||
// MAIN_DECLARATION
|
||||
// {
|
||||
// GLSL code here
|
||||
// }
|
||||
|
||||
/// configuration
|
||||
// use macros that will be default with Ogre 15
|
||||
// #define USE_OGRE_FROM_FUTURE
|
||||
|
||||
// @public-api
|
||||
|
||||
#if defined(OGRE_HLSL) || defined(OGRE_CG)
|
||||
// HLSL
|
||||
#include "HLSL_SM4Support.hlsl"
|
||||
#define vec2 float2
|
||||
#define vec3 float3
|
||||
#define vec4 float4
|
||||
#define mat3 float3x3
|
||||
#define mat4 float4x4
|
||||
|
||||
#define ivec2 int2
|
||||
#define ivec3 int3
|
||||
#define ivec4 int4
|
||||
|
||||
#define texture1D tex1D
|
||||
#define texture2D tex2D
|
||||
#define texture3D tex3D
|
||||
#define texture2DArray tex2DARRAY
|
||||
#define textureCube texCUBE
|
||||
#define shadow2D tex2Dcmp
|
||||
#define texture2DProj tex2Dproj
|
||||
vec4 texture2DLod(sampler2D s, vec2 v, float lod) { return tex2Dlod(s, vec4(v.x, v.y, 0, lod)); }
|
||||
|
||||
#define samplerCube samplerCUBE
|
||||
vec4 textureCubeLod(samplerCube s, vec3 v, float lod) { return texCUBElod(s, vec4(v.x, v.y, v.z, lod)); }
|
||||
|
||||
#define sampler2DShadow Sampler2DShadow
|
||||
|
||||
#define mix lerp
|
||||
#define fract frac
|
||||
#define inversesqrt rsqrt
|
||||
#define dFdx ddx
|
||||
#define dFdy ddy
|
||||
|
||||
float mod(float _a, float _b) { return _a - _b * floor(_a / _b); }
|
||||
vec2 mod(vec2 _a, vec2 _b) { return _a - _b * floor(_a / _b); }
|
||||
vec3 mod(vec3 _a, vec3 _b) { return _a - _b * floor(_a / _b); }
|
||||
vec4 mod(vec4 _a, vec4 _b) { return _a - _b * floor(_a / _b); }
|
||||
|
||||
vec2 vec2_splat(float x) { return vec2(x, x); }
|
||||
vec3 vec3_splat(float x) { return vec3(x, x, x); }
|
||||
vec4 vec4_splat(float x) { return vec4(x, x, x, x); }
|
||||
|
||||
mat4 mtxFromRows(vec4 a, vec4 b, vec4 c, vec4 d)
|
||||
{
|
||||
return mat4(a, b, c, d);
|
||||
}
|
||||
|
||||
mat3 mtxFromRows(vec3 a, vec3 b, vec3 c)
|
||||
{
|
||||
return mat3(a, b, c);
|
||||
}
|
||||
|
||||
mat3 mtxFromCols(vec3 a, vec3 b, vec3 c)
|
||||
{
|
||||
return transpose(mat3(a, b, c));
|
||||
}
|
||||
|
||||
#define STATIC static
|
||||
|
||||
#define OGRE_UNIFORMS_BEGIN
|
||||
#define OGRE_UNIFORMS_END
|
||||
|
||||
#define MAIN_PARAMETERS void main(
|
||||
|
||||
#ifdef OGRE_VERTEX_SHADER
|
||||
#define MAIN_DECLARATION out float4 gl_Position : POSITION)
|
||||
#else
|
||||
#define MAIN_DECLARATION in float4 gl_FragCoord : POSITION, out float4 gl_FragColor : COLOR)
|
||||
#endif
|
||||
|
||||
#define IN(decl, sem) in decl : sem,
|
||||
#define OUT(decl, sem) out decl : sem,
|
||||
#elif defined(OGRE_METAL)
|
||||
#define vec2 float2
|
||||
#define vec3 float3
|
||||
#define vec4 float4
|
||||
#define mat3 metal::float3x3
|
||||
#define mat4 metal::float4x4
|
||||
|
||||
#define IN(decl, sem) decl [[ attribute(sem) ]];
|
||||
#else
|
||||
// GLSL
|
||||
#include "GLSL_GL3Support.glsl"
|
||||
|
||||
#ifdef VULKAN
|
||||
#define _UNIFORM_BINDING(b) layout(binding = b + 2) uniform
|
||||
#elif __VERSION__ >= 420
|
||||
#define _UNIFORM_BINDING(b) layout(binding = b) uniform
|
||||
#else
|
||||
#define _UNIFORM_BINDING(b) uniform
|
||||
#endif
|
||||
|
||||
#define SAMPLER1D(name, reg) _UNIFORM_BINDING(reg) sampler1D name
|
||||
#define SAMPLER2D(name, reg) _UNIFORM_BINDING(reg) sampler2D name
|
||||
#define SAMPLER3D(name, reg) _UNIFORM_BINDING(reg) sampler3D name
|
||||
#define SAMPLER2DARRAY(name, reg) _UNIFORM_BINDING(reg) sampler2DArray name
|
||||
#define SAMPLERCUBE(name, reg) _UNIFORM_BINDING(reg) samplerCube name
|
||||
#define SAMPLER2DSHADOW(name, reg) _UNIFORM_BINDING(reg) sampler2DShadow name
|
||||
|
||||
#define saturate(x) clamp(x, 0.0, 1.0)
|
||||
#define mul(a, b) ((a) * (b))
|
||||
|
||||
#define vec2_splat vec2
|
||||
#define vec3_splat vec3
|
||||
#define vec4_splat vec4
|
||||
|
||||
mat4 mtxFromRows(vec4 a, vec4 b, vec4 c, vec4 d)
|
||||
{
|
||||
return transpose(mat4(a, b, c, d));
|
||||
}
|
||||
|
||||
mat3 mtxFromRows(vec3 a, vec3 b, vec3 c)
|
||||
{
|
||||
return transpose(mat3(a, b, c));
|
||||
}
|
||||
|
||||
mat3 mtxFromCols(vec3 a, vec3 b, vec3 c)
|
||||
{
|
||||
return mat3(a, b, c);
|
||||
}
|
||||
|
||||
#define STATIC
|
||||
|
||||
#define MAIN_PARAMETERS
|
||||
#define MAIN_DECLARATION void main()
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(OGRE_HLSL) && !defined(OGRE_CG)
|
||||
// semantics as aliases for attribute locations
|
||||
#define POSITION 0
|
||||
#define BLENDWEIGHT 1
|
||||
#define NORMAL 2
|
||||
#define COLOR0 3
|
||||
#define COLOR1 4
|
||||
#define COLOR COLOR0
|
||||
#define FOG 5
|
||||
#define BLENDINDICES 7
|
||||
#define TEXCOORD0 8
|
||||
#define TEXCOORD1 9
|
||||
#define TEXCOORD2 10
|
||||
#define TEXCOORD3 11
|
||||
#define TEXCOORD4 12
|
||||
#define TEXCOORD5 13
|
||||
#define TEXCOORD6 14
|
||||
#define TEXCOORD7 15
|
||||
#define TANGENT 14
|
||||
#endif
|
||||
|
||||
#define OGRE_UNIFORMS(params) OGRE_UNIFORMS_BEGIN params OGRE_UNIFORMS_END
|
||||
|
||||
// GL_EXT_shader_explicit_arithmetic_types polyfill
|
||||
#ifdef OGRE_GLSLES
|
||||
#define float32_t highp float
|
||||
#define f32vec2 highp vec2
|
||||
#define f32vec3 highp vec3
|
||||
#define f32vec4 highp vec4
|
||||
#else
|
||||
#define float32_t float
|
||||
#define f32vec2 vec2
|
||||
#define f32vec3 vec3
|
||||
#define f32vec4 vec4
|
||||
#endif
|
||||
85
resources/main/Shadow.material
Normal file
@@ -0,0 +1,85 @@
|
||||
// This file is part of the OGRE project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at https://www.ogre3d.org/licensing.
|
||||
|
||||
material Ogre/TextureShadowCaster
|
||||
{
|
||||
receive_shadows false
|
||||
technique
|
||||
{
|
||||
pass
|
||||
{
|
||||
// Lighting has to be on, because we need shadow coloured objects
|
||||
// Note that because we can't predict vertex programs, we'll have to
|
||||
// bind light values to those, and so we bind White to ambient
|
||||
// reflectance, and we'll set the ambient colour to the shadow colour
|
||||
ambient 1 1 1
|
||||
diffuse 0 0 0
|
||||
specular 0 0 0 1
|
||||
emissive 0 0 0
|
||||
fog_override true none
|
||||
// set depth bias in case this is used with PF_DEPTH
|
||||
depth_bias -1 -1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
material Ogre/StencilShadowModulationPass
|
||||
{
|
||||
technique
|
||||
{
|
||||
pass
|
||||
{
|
||||
lighting off
|
||||
scene_blend modulate
|
||||
depth_write off
|
||||
depth_check off
|
||||
cull_hardware none
|
||||
|
||||
vertex_program_ref Ogre/ShadowBlendVP {}
|
||||
fragment_program_ref Ogre/ShadowBlendFP {}
|
||||
texture_unit {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
material Ogre/StencilShadowVolumes
|
||||
{
|
||||
technique
|
||||
{
|
||||
pass
|
||||
{
|
||||
// program will be set dynamically to match light type
|
||||
vertex_program_ref Ogre/ShadowExtrudeDirLightFinite
|
||||
{
|
||||
// however, the parameters here are shared between all programs
|
||||
param_named_auto worldviewproj_matrix worldviewproj_matrix
|
||||
param_named_auto light_position_object_space light_position_object_space 0
|
||||
param_named_auto shadow_extrusion_distance shadow_extrusion_distance 0
|
||||
}
|
||||
fragment_program_ref Ogre/ShadowBlendFP {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
material Ogre/Debug/ShadowVolumes
|
||||
{
|
||||
technique
|
||||
{
|
||||
pass
|
||||
{
|
||||
depth_write off
|
||||
scene_blend add
|
||||
cull_hardware none
|
||||
|
||||
// program will be set dynamically to match light type
|
||||
vertex_program_ref Ogre/ShadowExtrudeDirLight
|
||||
{
|
||||
// however, the parameters here are shared between all programs
|
||||
param_named_auto worldviewproj_matrix worldviewproj_matrix
|
||||
param_named_auto light_position_object_space light_position_object_space 0
|
||||
}
|
||||
fragment_program_ref Ogre/ShadowBlendFP {}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
resources/main/ShadowBlend.frag
Normal file
@@ -0,0 +1,11 @@
|
||||
#include <OgreUnifiedShader.h>
|
||||
|
||||
OGRE_UNIFORMS(
|
||||
uniform vec4 shadowColor;
|
||||
)
|
||||
|
||||
MAIN_PARAMETERS
|
||||
MAIN_DECLARATION
|
||||
{
|
||||
gl_FragColor = shadowColor;
|
||||
}
|
||||
12
resources/main/ShadowBlend.vert
Normal file
@@ -0,0 +1,12 @@
|
||||
#include <OgreUnifiedShader.h>
|
||||
|
||||
OGRE_UNIFORMS(
|
||||
uniform mat4 worldViewProj;
|
||||
)
|
||||
|
||||
MAIN_PARAMETERS
|
||||
IN(vec4 vertex, POSITION)
|
||||
MAIN_DECLARATION
|
||||
{
|
||||
gl_Position = mul(worldViewProj, vertex);
|
||||
}
|
||||
18
resources/main/ShadowExtrudeDirLight.vert
Normal file
@@ -0,0 +1,18 @@
|
||||
#include <OgreUnifiedShader.h>
|
||||
|
||||
// Directional light extrude
|
||||
uniform mat4 worldviewproj_matrix;
|
||||
uniform vec4 light_position_object_space; // homogenous, object space
|
||||
|
||||
MAIN_PARAMETERS
|
||||
IN(vec4 uv0, TEXCOORD0)
|
||||
IN(vec4 position, POSITION)
|
||||
MAIN_DECLARATION
|
||||
{
|
||||
// Extrusion in object space
|
||||
// Vertex unmodified if w==1, extruded if w==0
|
||||
vec4 newpos =
|
||||
(uv0.xxxx * (position + light_position_object_space)) - light_position_object_space;
|
||||
|
||||
gl_Position = mul(worldviewproj_matrix, newpos);
|
||||
}
|
||||
22
resources/main/ShadowExtrudeDirLightFinite.vert
Normal file
@@ -0,0 +1,22 @@
|
||||
#include <OgreUnifiedShader.h>
|
||||
|
||||
// Directional light extrude - FINITE
|
||||
uniform mat4 worldviewproj_matrix;
|
||||
uniform vec4 light_position_object_space; // homogenous, object space
|
||||
uniform float shadow_extrusion_distance; // how far to extrude
|
||||
|
||||
MAIN_PARAMETERS
|
||||
IN(vec4 uv0, TEXCOORD0)
|
||||
IN(vec4 position, POSITION)
|
||||
MAIN_DECLARATION
|
||||
{
|
||||
// Extrusion in object space
|
||||
// Vertex unmodified if w==1, extruded if w==0
|
||||
vec3 extrusionDir = - light_position_object_space.xyz;
|
||||
extrusionDir = normalize(extrusionDir);
|
||||
|
||||
vec4 newpos = vec4(position.xyz +
|
||||
((1.0 - uv0.x) * shadow_extrusion_distance * extrusionDir), 1.0);
|
||||
|
||||
gl_Position = mul(worldviewproj_matrix, newpos);
|
||||
}
|
||||
19
resources/main/ShadowExtrudePointLight.vert
Normal file
@@ -0,0 +1,19 @@
|
||||
#include <OgreUnifiedShader.h>
|
||||
|
||||
// Point light shadow volume extrude
|
||||
uniform mat4 worldviewproj_matrix;
|
||||
uniform vec4 light_position_object_space; // homogenous, object space
|
||||
|
||||
MAIN_PARAMETERS
|
||||
IN(vec4 uv0, TEXCOORD0)
|
||||
IN(vec4 position, POSITION)
|
||||
MAIN_DECLARATION
|
||||
{
|
||||
// Extrusion in object space
|
||||
// Vertex unmodified if w==1, extruded if w==0
|
||||
vec4 newpos =
|
||||
(uv0.xxxx * light_position_object_space) +
|
||||
vec4(position.xyz - light_position_object_space.xyz, 0.0);
|
||||
|
||||
gl_Position = mul(worldviewproj_matrix, newpos);
|
||||
}
|
||||
22
resources/main/ShadowExtrudePointLightFinite.vert
Normal file
@@ -0,0 +1,22 @@
|
||||
#include <OgreUnifiedShader.h>
|
||||
|
||||
// Point light shadow volume extrude - FINITE
|
||||
uniform mat4 worldviewproj_matrix;
|
||||
uniform vec4 light_position_object_space; // homogenous, object space
|
||||
uniform float shadow_extrusion_distance; // how far to extrude
|
||||
|
||||
MAIN_PARAMETERS
|
||||
IN(vec4 uv0, TEXCOORD0)
|
||||
IN(vec4 position, POSITION)
|
||||
MAIN_DECLARATION
|
||||
{
|
||||
// Extrusion in object space
|
||||
// Vertex unmodified if w==1, extruded if w==0
|
||||
vec3 extrusionDir = position.xyz - light_position_object_space.xyz;
|
||||
extrusionDir = normalize(extrusionDir);
|
||||
|
||||
vec4 newpos = vec4(position.xyz +
|
||||
((1.0 - uv0.x) * shadow_extrusion_distance * extrusionDir), 1.0);
|
||||
|
||||
gl_Position = mul(worldviewproj_matrix, newpos);
|
||||
}
|
||||
41
resources/main/ShadowVolumeExtude.program
Normal file
@@ -0,0 +1,41 @@
|
||||
// This file is part of the OGRE project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at https://www.ogre3d.org/licensing.
|
||||
|
||||
vertex_program Ogre/ShadowBlendVP glsl glsles hlsl glslang
|
||||
{
|
||||
source ShadowBlend.vert
|
||||
default_params
|
||||
{
|
||||
param_named_auto worldViewProj worldviewproj_matrix
|
||||
}
|
||||
}
|
||||
|
||||
fragment_program Ogre/ShadowBlendFP glsl glsles hlsl glslang
|
||||
{
|
||||
source ShadowBlend.frag
|
||||
default_params
|
||||
{
|
||||
param_named_auto shadowColor shadow_colour
|
||||
}
|
||||
}
|
||||
|
||||
vertex_program Ogre/ShadowExtrudePointLight glsl glsles hlsl
|
||||
{
|
||||
source ShadowExtrudePointLight.vert
|
||||
}
|
||||
|
||||
vertex_program Ogre/ShadowExtrudeDirLight glsl glsles hlsl
|
||||
{
|
||||
source ShadowExtrudeDirLight.vert
|
||||
}
|
||||
|
||||
vertex_program Ogre/ShadowExtrudePointLightFinite glsl glsles hlsl
|
||||
{
|
||||
source ShadowExtrudePointLightFinite.vert
|
||||
}
|
||||
|
||||
vertex_program Ogre/ShadowExtrudeDirLightFinite glsl glsles hlsl
|
||||
{
|
||||
source ShadowExtrudeDirLightFinite.vert
|
||||
}
|
||||
BIN
resources/main/spot_shadow_fade.dds
Normal file
45
resources/shaderlib/FFPLib_AlphaTest.glsl
Normal file
@@ -0,0 +1,45 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Program Name: FFPLib_AlphaTest
|
||||
// Program Desc: Alpha test function.
|
||||
// Program Type: Vertex/Pixel shader
|
||||
// Language: GLSL
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#define CMPF_ALWAYS_FAIL 0
|
||||
#define CMPF_ALWAYS_PASS 1
|
||||
#define CMPF_LESS 2
|
||||
#define CMPF_LESS_EQUAL 3
|
||||
#define CMPF_EQUAL 4
|
||||
#define CMPF_NOT_EQUAL 5
|
||||
#define CMPF_GREATER_EQUAL 6
|
||||
#define CMPF_GREATER 7
|
||||
|
||||
bool Alpha_Func(in int func, in float alphaRef, in float alphaValue)
|
||||
{
|
||||
// ES2 does not have switch
|
||||
if(func == CMPF_ALWAYS_PASS)
|
||||
return true;
|
||||
else if(func == CMPF_LESS)
|
||||
return alphaValue < alphaRef;
|
||||
else if(func == CMPF_LESS_EQUAL)
|
||||
return alphaValue <= alphaRef;
|
||||
else if(func == CMPF_EQUAL)
|
||||
return alphaValue == alphaRef;
|
||||
else if(func == CMPF_NOT_EQUAL)
|
||||
return alphaValue != alphaRef;
|
||||
else if(func == CMPF_GREATER_EQUAL)
|
||||
return alphaValue >= alphaRef;
|
||||
else if(func == CMPF_GREATER)
|
||||
return alphaValue > alphaRef;
|
||||
|
||||
// CMPF_ALWAYS_FAIL and default
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void FFP_Alpha_Test(in float func, in float alphaRef, in vec4 texel)
|
||||
{
|
||||
bool pass_ = Alpha_Func(int(func), alphaRef, texel.a);
|
||||
if (!pass_)
|
||||
discard;
|
||||
}
|
||||
92
resources/shaderlib/FFPLib_Fog.glsl
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
-----------------------------------------------------------------------------
|
||||
This source file is part of OGRE
|
||||
(Object-oriented Graphics Rendering Engine)
|
||||
For the latest info, see http://www.ogre3d.org
|
||||
|
||||
Copyright (c) 2000-2014 Torus Knot Software Ltd
|
||||
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.
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Program Name: FFPLib_Fog
|
||||
// Program Desc: Fog functions of the FFP.
|
||||
// Program Type: Vertex/Pixel shader
|
||||
// Language: GLSL
|
||||
// Notes: Implements core functions needed by FFPFog class.
|
||||
// Based on fog engine.
|
||||
// See http://msdn.microsoft.com/en-us/library/bb173398.aspx
|
||||
// Vertex based fog: the w component of the out position is used
|
||||
// as the distance parameter to fog formulas. This is basically the z coordinate
|
||||
// in world space. See pixel fog under D3D docs. The fog factor is computed according
|
||||
// to each formula, then clamped and output to the pixel shader.
|
||||
// Pixel based fog: the w component of the out position is passed to pixel shader
|
||||
// that computes the fog factor based on it.
|
||||
// Both techniques use the fog factor in the end of the pixel shader to blend
|
||||
// the output color with the fog color.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#define FOG_EXP 1
|
||||
#define FOG_EXP2 2
|
||||
#define FOG_LINEAR 3
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void FFP_FogFactor(in float depth,
|
||||
in vec4 fogParams,
|
||||
out float oFogFactor)
|
||||
{
|
||||
float distance = abs(depth);
|
||||
|
||||
#if FOG_TYPE == FOG_LINEAR
|
||||
float fogFactor = (fogParams.z - distance) * fogParams.w;
|
||||
#elif FOG_TYPE == FOG_EXP
|
||||
float x = distance*fogParams.x;
|
||||
float fogFactor = 1.0 / exp(x);
|
||||
#elif FOG_TYPE == FOG_EXP2
|
||||
float x = (distance*fogParams.x*distance*fogParams.x);
|
||||
float fogFactor = 1.0 / exp(x);
|
||||
#endif
|
||||
|
||||
oFogFactor = saturate(fogFactor);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void FFP_PixelFog_PositionDepth(in mat4 mWorld,
|
||||
in vec3 cameraPos,
|
||||
in vec4 pos,
|
||||
out vec3 oPosView,
|
||||
out float oDepth)
|
||||
{
|
||||
vec4 vOutPos = mul(mWorld, pos);
|
||||
oPosView = vOutPos.xyz - cameraPos;
|
||||
oDepth = length(oPosView);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void FFP_PixelFog(in float depth,
|
||||
in vec4 fogParams,
|
||||
in vec4 fogColor,
|
||||
in vec4 baseColor,
|
||||
out vec4 oColor)
|
||||
{
|
||||
float fogFactor = 0.0;
|
||||
FFP_FogFactor(depth, fogParams, fogFactor);
|
||||
oColor = mix(fogColor, baseColor, fogFactor);
|
||||
}
|
||||
144
resources/shaderlib/FFPLib_Texturing.glsl
Normal file
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
-----------------------------------------------------------------------------
|
||||
This source file is part of OGRE
|
||||
(Object-oriented Graphics Rendering Engine)
|
||||
For the latest info, see http://www.ogre3d.org
|
||||
|
||||
Copyright (c) 2000-2014 Torus Knot Software Ltd
|
||||
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.
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Program Name: FFPLib_Texturing
|
||||
// Program Desc: Texture functions of the FFP.
|
||||
// Program Type: Vertex/Pixel shader
|
||||
// Language: GLSL
|
||||
// Notes: Implements core functions for FFPTexturing class.
|
||||
// based on texturing operations needed by render system.
|
||||
// Implements texture coordinate processing:
|
||||
// see http://msdn.microsoft.com/en-us/library/bb206247.aspx
|
||||
// Implements texture blending operation:
|
||||
// see http://msdn.microsoft.com/en-us/library/bb206241.aspx
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void FFP_TransformTexCoord(in mat4 m, in vec2 v, out vec2 vOut)
|
||||
{
|
||||
vOut = mul(m, vec4(v, 0.0, 1.0)).xy;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void FFP_TransformTexCoord(in mat4 m, in vec4 v, out vec2 vOut)
|
||||
{
|
||||
vOut = mul(m, v).xy;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void FFP_TransformTexCoord(in mat4 m, in vec3 v, out vec3 vOut)
|
||||
{
|
||||
vOut = mul(m, vec4(v, 1.0)).xyz;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void FFP_GenerateTexCoord_EnvMap_Normal(in mat3 mWorldIT,
|
||||
in vec3 vNormal,
|
||||
out vec3 vOut)
|
||||
{
|
||||
vOut = normalize(mul(mWorldIT, vNormal));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void FFP_GenerateTexCoord_EnvMap_Sphere(in mat4 mWorldView,
|
||||
in mat3 mWorldIT,
|
||||
in vec4 vPos,
|
||||
in vec3 vNormal,
|
||||
out vec2 vOut)
|
||||
{
|
||||
vec3 normal = normalize( mul(mWorldIT, vNormal));
|
||||
vec3 eyedir = normalize(mul(mWorldView, vPos)).xyz;
|
||||
vec3 r = reflect(eyedir, normal);
|
||||
r.z += 1.0;
|
||||
float two_p = 2.0 * length(r);
|
||||
vOut = vec2(0.5 + r.x / two_p, 0.5 - r.y / two_p);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void FFP_GenerateTexCoord_EnvMap_Reflect(in mat4 mWorld,
|
||||
in mat4 mWorldIT,
|
||||
in vec3 vCamPos,
|
||||
in vec3 vNormal,
|
||||
in vec4 vPos,
|
||||
out vec3 vOut)
|
||||
{
|
||||
vec3 vWorldNormal = normalize(mul(mWorldIT, vec4(vNormal, 0.0)).xyz);
|
||||
vec3 vWorldPos = mul(mWorld, vPos).xyz;
|
||||
vec3 vEyeDir = normalize(vWorldPos - vCamPos);
|
||||
|
||||
vec3 vReflect = reflect(vEyeDir, vWorldNormal);
|
||||
vReflect.z *= -1.0;
|
||||
|
||||
vOut = vReflect;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void FFP_AddSmooth(in float vIn0, in float vIn1, out float vOut)
|
||||
{
|
||||
vOut = vIn0 + vIn1 - (vIn0 * vIn1);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void FFP_AddSmooth(in vec2 vIn0, in vec2 vIn1, out vec2 vOut)
|
||||
{
|
||||
vOut = vIn0 + vIn1 - (vIn0 * vIn1);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void FFP_AddSmooth(in vec3 vIn0, in vec3 vIn1, out vec3 vOut)
|
||||
{
|
||||
vOut = vIn0 + vIn1 - (vIn0 * vIn1);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void FFP_AddSmooth(in vec4 vIn0, in vec4 vIn1, out vec4 vOut)
|
||||
{
|
||||
vOut = vIn0 + vIn1 - (vIn0 * vIn1);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void FFP_DotProduct(in float vIn0, in float vIn1, out float vOut)
|
||||
{
|
||||
vOut = dot(vIn0, vIn1);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void FFP_DotProduct(in vec2 vIn0, in vec2 vIn1, out vec2 vOut)
|
||||
{
|
||||
vOut = vec2_splat(dot(vIn0, vIn1));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void FFP_DotProduct(in vec3 vIn0, in vec3 vIn1, out vec3 vOut)
|
||||
{
|
||||
vOut = vec3_splat(dot(vIn0, vIn1));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void FFP_DotProduct(in vec4 vIn0, in vec4 vIn1, out vec4 vOut)
|
||||
{
|
||||
vOut = vec4_splat(dot(vIn0, vIn1));
|
||||
}
|
||||
100
resources/shaderlib/FFPLib_Transform.glsl
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
-----------------------------------------------------------------------------
|
||||
This source file is part of OGRE
|
||||
(Object-oriented Graphics Rendering Engine)
|
||||
For the latest info, see http://www.ogre3d.org
|
||||
|
||||
Copyright (c) 2000-2014 Torus Knot Software Ltd
|
||||
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.
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Program Name: FFPLib_Transform
|
||||
// Program Desc: Transform functions of the FFP.
|
||||
// Program Type: Vertex shader
|
||||
// Language: GLSL
|
||||
// Notes: Implements core functions for FFPTransform class.
|
||||
// based on transform engine.
|
||||
// See http://msdn.microsoft.com/en-us/library/bb206269.aspx
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void FFP_Transform(in mat4 m,
|
||||
in vec4 v,
|
||||
out vec3 vOut)
|
||||
{
|
||||
vOut = mul(m, v).xyz;
|
||||
}
|
||||
|
||||
#ifdef OGRE_HLSL
|
||||
void FFP_Transform(in float3x4 m,
|
||||
in float4 v,
|
||||
out float3 vOut)
|
||||
{
|
||||
vOut = mul(m, v);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void FFP_Transform(in float3x4 m,
|
||||
in float3 v,
|
||||
out float3 vOut)
|
||||
{
|
||||
vOut = mul((float3x3)m, v);
|
||||
}
|
||||
#elif !defined(OGRE_GLSLES) || OGRE_GLSLES > 100
|
||||
//-----------------------------------------------------------------------------
|
||||
void FFP_Transform(in mat3x4 m,
|
||||
in vec4 v,
|
||||
out vec3 vOut)
|
||||
{
|
||||
/* transpose non-square uniform matrix for correct row-major > column-major mapping
|
||||
* to keep the indexing inside the shader so mat[0] returns the same data in both GLSL and HLSL
|
||||
* although it will be the first row in HLSL and the first column in GLSL
|
||||
*/
|
||||
vOut = v * m;
|
||||
}
|
||||
|
||||
void FFP_Transform(in mat3x4 m,
|
||||
in vec3 v,
|
||||
out vec3 vOut)
|
||||
{
|
||||
vOut = v * mat3(m);
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void FFP_Transform(in mat4 m,
|
||||
in vec3 v,
|
||||
out vec3 vOut)
|
||||
{
|
||||
#ifdef OGRE_HLSL
|
||||
vOut = mul((float3x3)m, v);
|
||||
#else
|
||||
vOut = mat3(m) * v;
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void FFP_DerivePointSize(in vec4 params,
|
||||
in float d,
|
||||
out float sz)
|
||||
{
|
||||
sz = params.x/sqrt(params.y + params.z*d + params.w*d*d);
|
||||
}
|
||||
88
resources/shaderlib/RTSLib_IBL.glsl
Normal file
@@ -0,0 +1,88 @@
|
||||
// This file is part of the OGRE project.
|
||||
// code adapted from Google Filament
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
vec3 specularDFG(const PixelParams pixel) {
|
||||
return mix(pixel.dfg.xxx, pixel.dfg.yyy, pixel.f0);
|
||||
}
|
||||
|
||||
vec3 decodeDataForIBL(const vec4 data) {
|
||||
return data.rgb;
|
||||
}
|
||||
|
||||
vec3 Irradiance_RoughnessOne(samplerCube light_iblSpecular, const vec3 n, float iblRoughnessOneLevel) {
|
||||
// note: lod used is always integer, hopefully the hardware skips tri-linear filtering
|
||||
return decodeDataForIBL(textureCubeLod(light_iblSpecular, n, iblRoughnessOneLevel));
|
||||
}
|
||||
|
||||
vec3 PrefilteredDFG_LUT(sampler2D light_iblDFG, float lod, float NoV) {
|
||||
// coord = sqrt(linear_roughness), which is the mapping used by cmgen.
|
||||
// OGRE Specific: y is flipped compared to Filament code
|
||||
return texture2DLod(light_iblDFG, vec2(NoV, 1.0 - lod), 0.0).rgb;
|
||||
}
|
||||
|
||||
float perceptualRoughnessToLod(float iblRoughnessOneLevel, float perceptualRoughness) {
|
||||
// The mapping below is a quadratic fit for log2(perceptualRoughness)+iblRoughnessOneLevel when
|
||||
// iblRoughnessOneLevel is 4. We found empirically that this mapping works very well for
|
||||
// a 256 cubemap with 5 levels used. But also scales well for other iblRoughnessOneLevel values.
|
||||
return iblRoughnessOneLevel * perceptualRoughness * (2.0 - perceptualRoughness);
|
||||
}
|
||||
|
||||
vec3 prefilteredRadiance(samplerCube light_iblSpecular, const vec3 r, float perceptualRoughness, float iblRoughnessOneLevel) {
|
||||
float lod = perceptualRoughnessToLod(iblRoughnessOneLevel, perceptualRoughness);
|
||||
return decodeDataForIBL(textureCubeLod(light_iblSpecular, r, lod));
|
||||
}
|
||||
|
||||
vec3 getSpecularDominantDirection(const vec3 n, const vec3 r, float roughness) {
|
||||
return mix(r, n, roughness * roughness);
|
||||
}
|
||||
|
||||
void evaluateIBL(inout PixelParams pixel,
|
||||
in vec3 vNormal,
|
||||
in vec3 viewPos,
|
||||
in mat4 invViewMat,
|
||||
in sampler2D dfgTex,
|
||||
in samplerCube iblEnvTex,
|
||||
in float iblRoughnessOneLevel,
|
||||
in float iblLuminance,
|
||||
inout vec3 color)
|
||||
{
|
||||
vec3 shading_normal = normalize(vNormal);
|
||||
vec3 shading_view = -normalize(viewPos);
|
||||
float shading_NoV = clampNoV(abs(dot(shading_normal, shading_view)));
|
||||
|
||||
// the above is currently duplicated with CookTorrance
|
||||
|
||||
vec3 shading_reflected = reflect(-shading_view, shading_normal);
|
||||
|
||||
// Pre-filtered DFG term used for image-based lighting
|
||||
pixel.dfg = PrefilteredDFG_LUT(dfgTex, pixel.perceptualRoughness, shading_NoV);
|
||||
|
||||
vec3 E = specularDFG(pixel);
|
||||
vec3 r = getSpecularDominantDirection(shading_normal, shading_reflected, pixel.roughness);
|
||||
|
||||
// OGRE specific: convert r and n back to world space for texture sampling
|
||||
r = normalize(mul(invViewMat, vec4(r, 0.0)).xyz);
|
||||
r.z *= -1.0;
|
||||
shading_normal = normalize(mul(invViewMat, vec4(shading_normal, 0.0)).xyz);
|
||||
|
||||
// specular layer
|
||||
vec3 Fr = E * prefilteredRadiance(iblEnvTex, r, pixel.perceptualRoughness, iblRoughnessOneLevel);
|
||||
|
||||
vec3 diffuseIrradiance = Irradiance_RoughnessOne(iblEnvTex, shading_normal, iblRoughnessOneLevel);
|
||||
vec3 Fd = pixel.diffuseColor * diffuseIrradiance * (1.0 - E);
|
||||
|
||||
Fr *= iblLuminance;
|
||||
Fd *= iblLuminance;
|
||||
|
||||
// Combine all terms
|
||||
// Note: iblLuminance is already premultiplied by the exposure
|
||||
|
||||
color = pow(color, vec3_splat(2.2)); // gamma to linear
|
||||
|
||||
color += Fr + Fd;
|
||||
|
||||
// linear to gamma
|
||||
color = pow(color, vec3_splat(1.0/2.2));
|
||||
color = saturate(color);
|
||||
}
|
||||
114
resources/shaderlib/RTSLib_LTC.glsl
Normal file
@@ -0,0 +1,114 @@
|
||||
// Real-Time Polygonal-Light Shading with Linearly Transformed Cosines
|
||||
// by Eric Heitz, Jonathan Dupuy, Stephen Hill and David Neubelt
|
||||
// code: https://github.com/selfshadow/ltc_code/
|
||||
// also: https://github.com/mrdoob/three.js/blob/master/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js
|
||||
// adapted for Ogre by Pavel Rojtberg
|
||||
|
||||
#define LUT_SIZE 64.0
|
||||
#define LUT_SCALE ((LUT_SIZE - 1.0)/LUT_SIZE)
|
||||
#define LUT_BIAS (0.5/LUT_SIZE)
|
||||
|
||||
vec3 IntegrateEdgeVec(vec3 v1, vec3 v2)
|
||||
{
|
||||
float x = dot(v1, v2);
|
||||
float y = abs(x);
|
||||
|
||||
float a = 0.8543985 + (0.4965155 + 0.0145206*y)*y;
|
||||
float b = 3.4175940 + (4.1616724 + y)*y;
|
||||
float v = a / b;
|
||||
|
||||
float theta_sintheta = (x > 0.0) ? v : 0.5*inversesqrt(max(1.0 - x*x, 1e-7)) - v;
|
||||
|
||||
return cross(v1, v2)*theta_sintheta;
|
||||
}
|
||||
|
||||
float LTC_Evaluate(vec3 N, vec3 V, vec3 P, mat3 Minv, vec3 points[4], sampler2D ltc_2)
|
||||
{
|
||||
vec3 dir = points[0] - P;
|
||||
vec3 lightDir = cross(points[1] - points[0], points[3] - points[0]);
|
||||
if(dot(dir, lightDir) < 0.0)
|
||||
return 0.0;
|
||||
|
||||
// construct orthonormal basis around N
|
||||
vec3 T1, T2;
|
||||
T1 = normalize(V - N*dot(V, N));
|
||||
T2 = cross(N, T1);
|
||||
|
||||
// rotate area light in (T1, T2, N) basis
|
||||
Minv = mul(Minv, mtxFromRows(T1, T2, N));
|
||||
|
||||
// polygon
|
||||
vec3 L[4];
|
||||
L[0] = mul(Minv, points[0] - P);
|
||||
L[1] = mul(Minv, points[1] - P);
|
||||
L[2] = mul(Minv, points[2] - P);
|
||||
L[3] = mul(Minv, points[3] - P);
|
||||
|
||||
// project rect onto sphere
|
||||
L[0] = normalize(L[0]);
|
||||
L[1] = normalize(L[1]);
|
||||
L[2] = normalize(L[2]);
|
||||
L[3] = normalize(L[3]);
|
||||
|
||||
vec3 vsum = vec3_splat(0.0);
|
||||
|
||||
vsum += IntegrateEdgeVec(L[0], L[1]);
|
||||
vsum += IntegrateEdgeVec(L[1], L[2]);
|
||||
vsum += IntegrateEdgeVec(L[2], L[3]);
|
||||
vsum += IntegrateEdgeVec(L[3], L[0]);
|
||||
|
||||
float len = length(vsum);
|
||||
float z = vsum.z/len;
|
||||
|
||||
// clipless approximation: tabulated horizon-clipped sphere
|
||||
// visually better than alternatives, but produces artifacts at low roughness values
|
||||
vec2 uv = vec2(z*0.5 + 0.5, len);
|
||||
uv = uv*LUT_SCALE + LUT_BIAS;
|
||||
|
||||
float scale = texture2D(ltc_2, uv).w;
|
||||
return len*scale;
|
||||
}
|
||||
|
||||
void InitRectPoints(vec3 center, vec3 ex, vec3 ey, out vec3 points[4])
|
||||
{
|
||||
points[0] = center - ex - ey;
|
||||
points[1] = center + ex - ey;
|
||||
points[2] = center + ex + ey;
|
||||
points[3] = center - ex + ey;
|
||||
}
|
||||
|
||||
void evaluateRectLight(sampler2D ltc_1, sampler2D ltc_2, float roughness, vec3 N, vec3 pos, vec3 lpos, vec3 halfwidth, vec3 halfheight,
|
||||
inout vec3 scol, inout vec3 dcol)
|
||||
{
|
||||
vec3 points[4];
|
||||
InitRectPoints(lpos, halfwidth, halfheight, points);
|
||||
|
||||
vec3 V = -normalize(pos);
|
||||
|
||||
float ndotv = saturate(dot(N, V));
|
||||
vec2 uv = vec2(roughness, sqrt(1.0 - ndotv));
|
||||
uv = uv*LUT_SCALE + LUT_BIAS;
|
||||
|
||||
vec4 t1 = texture2D(ltc_1, uv);
|
||||
|
||||
mat3 Minv = mtxFromCols(
|
||||
vec3(t1.x, 0.0, t1.y),
|
||||
vec3( 0.0, 1.0, 0.0),
|
||||
vec3(t1.z, 0.0, t1.w)
|
||||
);
|
||||
|
||||
float spec = LTC_Evaluate(N, V, pos, Minv, points, ltc_2);
|
||||
|
||||
// LTC Fresnel Approximation by Stephen Hill
|
||||
// http://blog.selfshadow.com/publications/s2016-advances/s2016_ltc_fresnel.pdf
|
||||
vec4 t2 = texture2D(ltc_2, uv);
|
||||
scol = (scol*t2.x + (1.0 - scol)*t2.y)*spec;
|
||||
|
||||
mat3 Meye = mat3(
|
||||
vec3(1.0, 0.0, 0.0),
|
||||
vec3(0.0, 1.0, 0.0),
|
||||
vec3(0.0, 0.0, 1.0)
|
||||
);
|
||||
|
||||
dcol *= LTC_Evaluate(N, V, pos, Meye, points, ltc_2);
|
||||
}
|
||||
18
resources/shaderlib/RTSLib_Lighting.glsl
Normal file
@@ -0,0 +1,18 @@
|
||||
// This file is part of the OGRE project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at https://www.ogre3d.org/licensing.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#define M_PI 3.14159265359
|
||||
|
||||
float getDistanceAttenuation(const vec3 params, float distance)
|
||||
{
|
||||
return 1.0 / (params.x + params.y * distance + params.z * distance * distance);
|
||||
}
|
||||
|
||||
float getAngleAttenuation(const vec3 params, const vec3 lightDir, const vec3 toLight)
|
||||
{
|
||||
float rho = dot(-lightDir, toLight);
|
||||
float fSpotE = saturate((rho - params.y) / (params.x - params.y));
|
||||
return pow(fSpotE, params.z);
|
||||
}
|
||||
17
resources/shaderlib/RTSSamplers.material
Normal file
@@ -0,0 +1,17 @@
|
||||
sampler Ogre/ShadowSampler
|
||||
{
|
||||
tex_address_mode border
|
||||
tex_border_colour 1 1 1 1
|
||||
}
|
||||
|
||||
sampler Ogre/DepthShadowSampler : Ogre/ShadowSampler
|
||||
{
|
||||
compare_test on
|
||||
comp_func less_equal
|
||||
}
|
||||
|
||||
sampler Ogre/LtcLUTSampler
|
||||
{
|
||||
filtering point linear point
|
||||
tex_address_mode clamp
|
||||
}
|
||||
246
resources/shaderlib/SGXLib_CookTorrance.glsl
Normal file
@@ -0,0 +1,246 @@
|
||||
// This file is part of the OGRE project.
|
||||
// code adapted from Google Filament
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#include "RTSLib_Lighting.glsl"
|
||||
|
||||
#ifdef HAVE_AREA_LIGHTS
|
||||
#include "RTSLib_LTC.glsl"
|
||||
#endif
|
||||
|
||||
#ifdef OGRE_GLSLES
|
||||
// min roughness such that (MIN_PERCEPTUAL_ROUGHNESS^4) > 0 in fp16 (i.e. 2^(-14/4), rounded up)
|
||||
#define MIN_PERCEPTUAL_ROUGHNESS 0.089
|
||||
#else
|
||||
#define MIN_PERCEPTUAL_ROUGHNESS 0.045
|
||||
#endif
|
||||
|
||||
#define MEDIUMP_FLT_MAX 65504.0
|
||||
#define saturateMediump(x) min(x, MEDIUMP_FLT_MAX)
|
||||
|
||||
#define MIN_N_DOT_V 1e-4
|
||||
|
||||
struct PixelParams
|
||||
{
|
||||
vec3 baseColor;
|
||||
vec3 diffuseColor;
|
||||
float perceptualRoughness;
|
||||
float roughness;
|
||||
vec3 f0;
|
||||
vec3 dfg;
|
||||
vec3 energyCompensation;
|
||||
};
|
||||
|
||||
float clampNoV(float NoV) {
|
||||
// Neubelt and Pettineo 2013, "Crafting a Next-gen Material Pipeline for The Order: 1886"
|
||||
return max(NoV, MIN_N_DOT_V);
|
||||
}
|
||||
|
||||
// Computes x^5 using only multiply operations.
|
||||
float pow5(float x) {
|
||||
float x2 = x * x;
|
||||
return x2 * x2 * x;
|
||||
}
|
||||
|
||||
// https://google.github.io/filament/Filament.md.html#materialsystem/diffusebrdf
|
||||
float Fd_Lambert() {
|
||||
return 1.0 / M_PI;
|
||||
}
|
||||
|
||||
// https://google.github.io/filament/Filament.md.html#materialsystem/specularbrdf/fresnel(specularf)
|
||||
vec3 F_Schlick(const vec3 f0, float f90, float VoH) {
|
||||
// Schlick 1994, "An Inexpensive BRDF Model for Physically-Based Rendering"
|
||||
return f0 + (f90 - f0) * pow5(1.0 - VoH);
|
||||
}
|
||||
|
||||
vec3 computeDiffuseColor(const vec3 baseColor, float metallic) {
|
||||
return baseColor.rgb * (1.0 - metallic);
|
||||
}
|
||||
|
||||
vec3 computeF0(const vec3 baseColor, float metallic, float reflectance) {
|
||||
return baseColor.rgb * metallic + (reflectance * (1.0 - metallic));
|
||||
}
|
||||
|
||||
float perceptualRoughnessToRoughness(float perceptualRoughness) {
|
||||
return perceptualRoughness * perceptualRoughness;
|
||||
}
|
||||
|
||||
// https://google.github.io/filament/Filament.md.html#materialsystem/specularbrdf/geometricshadowing(specularg)
|
||||
float V_SmithGGXCorrelated(float roughness, float NoV, float NoL) {
|
||||
// Heitz 2014, "Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs"
|
||||
float a2 = roughness * roughness;
|
||||
// TODO: lambdaV can be pre-computed for all the lights, it should be moved out of this function
|
||||
float lambdaV = NoL * sqrt((NoV - a2 * NoV) * NoV + a2);
|
||||
float lambdaL = NoV * sqrt((NoL - a2 * NoL) * NoL + a2);
|
||||
float v = 0.5 / (lambdaV + lambdaL);
|
||||
// a2=0 => v = 1 / 4*NoL*NoV => min=1/4, max=+inf
|
||||
// a2=1 => v = 1 / 2*(NoL+NoV) => min=1/4, max=+inf
|
||||
// clamp to the maximum value representable in mediump
|
||||
return saturateMediump(v);
|
||||
}
|
||||
|
||||
// https://google.github.io/filament/Filament.md.html#materialsystem/specularbrdf/normaldistributionfunction(speculard)
|
||||
float D_GGX(float roughness, float NoH, const vec3 h, const vec3 n) {
|
||||
// Walter et al. 2007, "Microfacet Models for Refraction through Rough Surfaces"
|
||||
|
||||
// In mediump, there are two problems computing 1.0 - NoH^2
|
||||
// 1) 1.0 - NoH^2 suffers floating point cancellation when NoH^2 is close to 1 (highlights)
|
||||
// 2) NoH doesn't have enough precision around 1.0
|
||||
// Both problem can be fixed by computing 1-NoH^2 in highp and providing NoH in highp as well
|
||||
|
||||
// However, we can do better using Lagrange's identity:
|
||||
// ||a x b||^2 = ||a||^2 ||b||^2 - (a . b)^2
|
||||
// since N and H are unit vectors: ||N x H||^2 = 1.0 - NoH^2
|
||||
// This computes 1.0 - NoH^2 directly (which is close to zero in the highlights and has
|
||||
// enough precision).
|
||||
// Overall this yields better performance, keeping all computations in mediump
|
||||
#ifdef OGRE_GLSLES
|
||||
vec3 NxH = cross(n, h);
|
||||
float oneMinusNoHSquared = dot(NxH, NxH);
|
||||
#else
|
||||
float oneMinusNoHSquared = 1.0 - NoH * NoH;
|
||||
#endif
|
||||
|
||||
float a = NoH * roughness;
|
||||
float k = roughness / (oneMinusNoHSquared + a * a);
|
||||
float d = k * k * (1.0 / M_PI);
|
||||
return saturateMediump(d);
|
||||
}
|
||||
|
||||
vec3 evaluateLight(
|
||||
in vec3 vNormal,
|
||||
in vec3 viewPos,
|
||||
in vec4 lightPos,
|
||||
in vec3 lightColor,
|
||||
in vec4 pointParams,
|
||||
in vec4 vLightDirView,
|
||||
in vec4 spotParams,
|
||||
in PixelParams pixel)
|
||||
{
|
||||
vec3 vLightView = lightPos.xyz;
|
||||
float fLightD = 0.0;
|
||||
|
||||
if (lightPos.w != 0.0)
|
||||
{
|
||||
vLightView -= viewPos; // to light
|
||||
fLightD = length(vLightView);
|
||||
|
||||
if(fLightD > pointParams.x)
|
||||
return vec3_splat(0.0);
|
||||
}
|
||||
|
||||
vLightView = normalize(vLightView);
|
||||
|
||||
vec3 vNormalView = normalize(vNormal);
|
||||
float NoL = saturate(dot(vNormalView, vLightView));
|
||||
|
||||
if(NoL <= 0.0)
|
||||
return vec3_splat(0.0); // not lit by this light
|
||||
|
||||
// https://google.github.io/filament/Filament.md.html#toc5.6.2
|
||||
float f90 = saturate(dot(pixel.f0, vec3_splat(50.0 * 0.33)));
|
||||
|
||||
vec3 vView = -normalize(viewPos);
|
||||
|
||||
// https://google.github.io/filament/Filament.md.html#materialsystem/standardmodelsummary
|
||||
vec3 h = normalize(vView + vLightView);
|
||||
float NoH = saturate(dot(vNormalView, h));
|
||||
float NoV = clampNoV(abs(dot(vNormalView, vView)));
|
||||
|
||||
float V = V_SmithGGXCorrelated(pixel.roughness, NoV, NoL);
|
||||
vec3 F = F_Schlick(pixel.f0, f90, NoH);
|
||||
float D = D_GGX(pixel.roughness, NoH, h, vNormalView);
|
||||
|
||||
vec3 Fr = (D * V) * F;
|
||||
vec3 Fd = pixel.diffuseColor * Fd_Lambert();
|
||||
|
||||
// https://google.github.io/filament/Filament.md.html#materialsystem/improvingthebrdfs/energylossinspecularreflectance
|
||||
vec3 color = NoL * lightColor * (Fr * pixel.energyCompensation + Fd);
|
||||
|
||||
color *= getDistanceAttenuation(pointParams.yzw, fLightD);
|
||||
|
||||
if(spotParams.w != 0.0)
|
||||
{
|
||||
color *= getAngleAttenuation(spotParams.xyz, vLightDirView.xyz, vLightView);
|
||||
}
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
void PBR_MakeParams(in vec3 baseColor, in vec2 mrParam, inout PixelParams pixel)
|
||||
{
|
||||
baseColor = pow(baseColor, vec3_splat(2.2));
|
||||
pixel.baseColor = baseColor;
|
||||
|
||||
float perceptualRoughness = mrParam.x;
|
||||
// Clamp the roughness to a minimum value to avoid divisions by 0 during lighting
|
||||
pixel.perceptualRoughness = clamp(perceptualRoughness, MIN_PERCEPTUAL_ROUGHNESS, 1.0);
|
||||
// Remaps the roughness to a perceptually linear roughness (roughness^2)
|
||||
pixel.roughness = perceptualRoughnessToRoughness(pixel.perceptualRoughness);
|
||||
|
||||
float metallic = saturate(mrParam.y);
|
||||
pixel.f0 = computeF0(baseColor, metallic, 0.04);
|
||||
pixel.diffuseColor = computeDiffuseColor(baseColor, metallic);
|
||||
|
||||
pixel.dfg = vec3_splat(0.5); // use full f0 for energy compensation
|
||||
pixel.energyCompensation = vec3_splat(0.0); // will be set later
|
||||
}
|
||||
|
||||
#if LIGHT_COUNT > 0
|
||||
void PBR_Lights(
|
||||
#ifdef SHADOWLIGHT_COUNT
|
||||
in float shadowFactor[SHADOWLIGHT_COUNT],
|
||||
#endif
|
||||
#ifdef HAVE_AREA_LIGHTS
|
||||
in sampler2D ltcLUT1,
|
||||
in sampler2D ltcLUT2,
|
||||
#endif
|
||||
in vec3 vNormal,
|
||||
in vec3 viewPos,
|
||||
in vec4 ambient,
|
||||
in vec4 lightPos[LIGHT_COUNT],
|
||||
in vec4 lightColor[LIGHT_COUNT],
|
||||
in vec4 pointParams[LIGHT_COUNT],
|
||||
in vec4 vLightDirView[LIGHT_COUNT],
|
||||
in vec4 spotParams[LIGHT_COUNT],
|
||||
in PixelParams pixel,
|
||||
inout vec3 vOutColour)
|
||||
{
|
||||
vOutColour = pow(vOutColour, vec3_splat(2.2)); // gamma to linear
|
||||
|
||||
// Energy compensation for multiple scattering in a microfacet model
|
||||
// See "Multiple-Scattering Microfacet BSDFs with the Smith Model"
|
||||
pixel.energyCompensation = 1.0 + pixel.f0 * (1.0 / pixel.dfg.y - 1.0);
|
||||
|
||||
for(int i = 0; i < LIGHT_COUNT; i++)
|
||||
{
|
||||
#ifdef HAVE_AREA_LIGHTS
|
||||
if(spotParams[i].w == 2.0)
|
||||
{
|
||||
// rect area light
|
||||
vec3 dcol = pixel.diffuseColor;
|
||||
vec3 scol = pixel.f0;
|
||||
evaluateRectLight(ltcLUT1, ltcLUT2, pixel.roughness, normalize(vNormal), viewPos,
|
||||
lightPos[i].xyz, spotParams[i].xyz, pointParams[i].xyz, scol, dcol);
|
||||
vOutColour += lightColor[i].xyz * (scol + dcol) * 4.0;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
vec3 lightVal = evaluateLight(vNormal, viewPos, lightPos[i], lightColor[i].xyz, pointParams[i], vLightDirView[i], spotParams[i],
|
||||
pixel);
|
||||
|
||||
#ifdef SHADOWLIGHT_COUNT
|
||||
if(i < SHADOWLIGHT_COUNT)
|
||||
lightVal *= shadowFactor[i];
|
||||
#endif
|
||||
vOutColour += lightVal;
|
||||
}
|
||||
|
||||
vOutColour += pixel.baseColor * pow(ambient.rgb, vec3_splat(2.2));
|
||||
|
||||
// linear to gamma
|
||||
vOutColour = pow(vOutColour, vec3_splat(1.0/2.2));
|
||||
|
||||
vOutColour = saturate(vOutColour);
|
||||
}
|
||||
#endif
|
||||
172
resources/shaderlib/SGXLib_DualQuaternion.glsl
Normal file
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
-----------------------------------------------------------------------------
|
||||
This source file is part of OGRE
|
||||
(Object-oriented Graphics Rendering Engine)
|
||||
For the latest info, see http://www.ogre3d.org
|
||||
|
||||
Copyright (c) 2000-2014 Torus Knot Software Ltd
|
||||
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.
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
//These functions are based on dqs.cg from http://isg.cs.tcd.ie/kavanl/dq/
|
||||
/* dqs.cg
|
||||
|
||||
Dual quaternion skinning vertex shaders (no shading computations)
|
||||
|
||||
Version 1.0.3, November 1st, 2007
|
||||
|
||||
Copyright (C) 2006-2007 University of Dublin, Trinity College, All Rights
|
||||
Reserved
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the author(s) be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
Author: Ladislav Kavan, kavanl@cs.tcd.ie
|
||||
|
||||
*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Program Name: SGXLib_DualQuaternion
|
||||
// Program Desc: Dual quaternion skinning functions.
|
||||
// Program Type: Vertex shader
|
||||
// Language: GLSL
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#if defined(OGRE_HLSL) || defined(OGRE_CG)
|
||||
// this is technically wrong, thats why we dont put it into OgreUnifiedShader.h
|
||||
#define mat2x4 float2x4
|
||||
#define mat3x4 float3x4
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void SGX_BlendWeight(in float blendWgt, in mat2x4 dualQuaternion, out mat2x4 vOut)
|
||||
{
|
||||
vOut = blendWgt*dualQuaternion;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void SGX_BlendWeight(in float blendWgt, in mat3x4 scaleShearMatrix, out mat3x4 vOut)
|
||||
{
|
||||
vOut = blendWgt*scaleShearMatrix;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Adjusts the sign of a dual quaternion depending on its orientation to the root dual quaternion
|
||||
void SGX_AntipodalityAdjustment(in mat2x4 dq0, in mat2x4 dq1,out mat2x4 dq2)
|
||||
{
|
||||
//Accurate antipodality handling. For speed increase, remove the following line,
|
||||
//though, the results will only be valid for rotations less than 180 degrees.
|
||||
dq2 = (dot(dq0[0], dq1[0]) < 0.0) ? dq1 * -1.0 : dq1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void SGX_CalculateBlendPosition(in vec3 position, in mat2x4 blendDQ, out vec4 vOut)
|
||||
{
|
||||
vec3 blendPosition = position + 2.0*cross(blendDQ[0].yzw, cross(blendDQ[0].yzw, position) + blendDQ[0].x*position);
|
||||
vec3 trans = 2.0*(blendDQ[0].x*blendDQ[1].yzw - blendDQ[1].x*blendDQ[0].yzw + cross(blendDQ[0].yzw, blendDQ[1].yzw));
|
||||
blendPosition += trans;
|
||||
|
||||
vOut = vec4(blendPosition, 1.0);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void SGX_CalculateBlendNormal(in vec3 normal, in mat2x4 blendDQ, out vec3 vOut)
|
||||
{
|
||||
vOut = normal + 2.0*cross(blendDQ[0].yzw, cross(blendDQ[0].yzw, normal) + blendDQ[0].x*normal);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void SGX_AdjointTransposeMatrix(in mat3x4 M, out mat3 vOut)
|
||||
{
|
||||
mat3 atM;
|
||||
atM[0][0] = M[2][2] * M[1][1] - M[1][2] * M[2][1];
|
||||
atM[0][1] = M[1][2] * M[2][0] - M[1][0] * M[2][2];
|
||||
atM[0][2] = M[1][0] * M[2][1] - M[2][0] * M[1][1];
|
||||
|
||||
atM[1][0] = M[0][2] * M[2][1] - M[2][2] * M[0][1];
|
||||
atM[1][1] = M[2][2] * M[0][0] - M[0][2] * M[2][0];
|
||||
atM[1][2] = M[2][0] * M[0][1] - M[0][0] * M[2][1];
|
||||
|
||||
atM[2][0] = M[1][2] * M[0][1] - M[0][2] * M[1][1];
|
||||
atM[2][1] = M[1][0] * M[0][2] - M[1][2] * M[0][0];
|
||||
atM[2][2] = M[0][0] * M[1][1] - M[1][0] * M[0][1];
|
||||
|
||||
vOut = atM;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void blendBonesDQ(mat2x4 bones_dq[BONE_COUNT], vec4 indices, vec4 weights, out mat2x4 blendDQ)
|
||||
{
|
||||
blendDQ = bones_dq[int(indices.x)] * weights.x;
|
||||
mat2x4 dqi;
|
||||
#ifdef CORRECT_ANTIPODALITY
|
||||
mat2x4 dq0 = blendDQ;
|
||||
#endif
|
||||
#if WEIGHT_COUNT > 1
|
||||
dqi = bones_dq[int(indices.y)] * weights.y;
|
||||
# ifdef CORRECT_ANTIPODALITY
|
||||
SGX_AntipodalityAdjustment(dq0, dqi, dqi);
|
||||
# endif
|
||||
blendDQ += dqi;
|
||||
#endif
|
||||
#if WEIGHT_COUNT > 2
|
||||
dqi = bones_dq[int(indices.z)] * weights.z;
|
||||
# ifdef CORRECT_ANTIPODALITY
|
||||
SGX_AntipodalityAdjustment(dq0, dqi, dqi);
|
||||
# endif
|
||||
blendDQ += dqi;
|
||||
#endif
|
||||
#if WEIGHT_COUNT > 3
|
||||
dqi = bones_dq[int(indices.w)] * weights.w;
|
||||
# ifdef CORRECT_ANTIPODALITY
|
||||
SGX_AntipodalityAdjustment(dq0, dqi, dqi);
|
||||
# endif
|
||||
blendDQ += dqi;
|
||||
#endif
|
||||
|
||||
blendDQ /= length(blendDQ[0]); // normalise dual quaternion
|
||||
}
|
||||
|
||||
void blendBonesMat3x4(mat3x4 bones_mat[BONE_COUNT], vec4 indices, vec4 weights, out mat3x4 blendMat)
|
||||
{
|
||||
blendMat = bones_mat[int(indices.x)] * weights.x;
|
||||
#if WEIGHT_COUNT > 1
|
||||
blendMat += bones_mat[int(indices.y)] * weights.y;
|
||||
#endif
|
||||
#if WEIGHT_COUNT > 2
|
||||
blendMat += bones_mat[int(indices.z)] * weights.z;
|
||||
#endif
|
||||
#if WEIGHT_COUNT > 3
|
||||
blendMat += bones_mat[int(indices.w)] * weights.w;
|
||||
#endif
|
||||
}
|
||||
183
resources/shaderlib/SGXLib_IntegratedPSSM.glsl
Normal file
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
-----------------------------------------------------------------------------
|
||||
This source file is part of OGRE
|
||||
(Object-oriented Graphics Rendering Engine)
|
||||
For the latest info, see http://www.ogre3d.org
|
||||
|
||||
Copyright (c) 2000-2014 Torus Knot Software Ltd
|
||||
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.
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
//-----------------------------------------------------------------------------
|
||||
// Program Name: SGXLib_IntegratedPSSM
|
||||
// Program Desc: Integrated PSSM functions.
|
||||
// Program Type: Vertex/Pixel shader
|
||||
// Language: GLSL
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifdef PSSM_SAMPLE_CMP
|
||||
#define SAMPLER_TYPE sampler2DShadow
|
||||
#else
|
||||
#define SAMPLER_TYPE sampler2D
|
||||
#endif
|
||||
|
||||
// default to 2x2 PCF
|
||||
#ifndef PCF_XSAMPLES
|
||||
#define PCF_XSAMPLES 2.0
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifdef SHADOWLIGHT_COUNT
|
||||
void SGX_ApplyShadowFactor_Modulative(in vec4 ambient,
|
||||
in float fShadowFactor[SHADOWLIGHT_COUNT],
|
||||
inout vec4 diffCol
|
||||
#ifdef USE_SPECULAR
|
||||
, inout vec4 specCol
|
||||
#endif
|
||||
)
|
||||
{
|
||||
float shadowFactor = fShadowFactor[0];
|
||||
for(int i = 1; i < SHADOWLIGHT_COUNT; ++i)
|
||||
shadowFactor *= fShadowFactor[i];
|
||||
|
||||
diffCol.rgb = mix(ambient.rgb, diffCol.rgb, shadowFactor);
|
||||
|
||||
#ifdef USE_SPECULAR
|
||||
specCol.rgb *= shadowFactor;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
float sampleDepth(in SAMPLER_TYPE shadowMap, vec2 uv, float depth)
|
||||
{
|
||||
#ifdef PSSM_SAMPLE_CMP
|
||||
# if defined(OGRE_GLSL) && OGRE_GLSL < 130
|
||||
return shadow2D(shadowMap, vec3(uv, depth)).r;
|
||||
# else
|
||||
return shadow2D(shadowMap, vec3(uv, depth));
|
||||
# endif
|
||||
#else
|
||||
return (depth <= texture2D(shadowMap, uv).r) ? 1.0 : 0.0;
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifdef PSSM_SAMPLE_COLOUR
|
||||
void SGX_ShadowPCF4(in sampler2D shadowMap, in vec4 shadowMapPos, in vec2 invTexSize, out float c)
|
||||
{
|
||||
c = texture2DProj(shadowMap, shadowMapPos).x;
|
||||
}
|
||||
#else
|
||||
void SGX_ShadowPCF4(in SAMPLER_TYPE shadowMap, in vec4 shadowMapPos, in vec2 invTexSize, out float c)
|
||||
{
|
||||
shadowMapPos = shadowMapPos / shadowMapPos.w;
|
||||
#if !defined(OGRE_REVERSED_Z) && !defined(OGRE_HLSL) && !defined(VULKAN)
|
||||
shadowMapPos.z = shadowMapPos.z * 0.5 + 0.5; // convert -1..1 to 0..1
|
||||
#endif
|
||||
vec2 uv = shadowMapPos.xy;
|
||||
|
||||
// depth must be clamped to support floating-point depth formats. This is to avoid comparing a
|
||||
// value from the depth texture (which is never greater than 1.0) with a greater-than-one
|
||||
// comparison value (which is possible with floating-point formats).
|
||||
float depth = clamp(shadowMapPos.z, 0.0, 1.0);
|
||||
|
||||
c = 0.0;
|
||||
float scale = 1.0;
|
||||
float offset = (PCF_XSAMPLES / 2.0 - 0.5) * scale;
|
||||
for (float y = -offset; y <= offset; y += scale)
|
||||
for (float x = -offset; x <= offset; x += scale)
|
||||
c += sampleDepth(shadowMap, uv + invTexSize * vec2(x, y), depth);
|
||||
|
||||
c /= PCF_XSAMPLES * PCF_XSAMPLES;
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void SGX_ComputeShadowFactor_PSSM3(in float fDepth,
|
||||
in vec4 vSplitPoints,
|
||||
in vec4 lightPosition0,
|
||||
in SAMPLER_TYPE shadowMap0,
|
||||
in vec2 invShadowMapSize0,
|
||||
#if PSSM_NUM_SPLITS > 2
|
||||
in vec4 lightPosition1,
|
||||
in SAMPLER_TYPE shadowMap1,
|
||||
in vec2 invShadowMapSize1,
|
||||
#endif
|
||||
#if PSSM_NUM_SPLITS > 3
|
||||
in vec4 lightPosition2,
|
||||
in SAMPLER_TYPE shadowMap2,
|
||||
in vec2 invShadowMapSize2,
|
||||
#endif
|
||||
in vec4 lightPosition3,
|
||||
in SAMPLER_TYPE shadowMap3,
|
||||
in vec2 invShadowMapSize3,
|
||||
out float oShadowFactor
|
||||
#ifdef DEBUG_PSSM
|
||||
, out vec4 oDiffuse
|
||||
#endif
|
||||
)
|
||||
{
|
||||
#if !defined(OGRE_REVERSED_Z) && !defined(OGRE_HLSL) && !defined(VULKAN)
|
||||
vSplitPoints = vSplitPoints * 0.5 + 0.5; // convert -1..1 to 0..1
|
||||
#endif
|
||||
|
||||
#ifdef OGRE_REVERSED_Z
|
||||
vSplitPoints = vec4_splat(1.0) - vSplitPoints;
|
||||
fDepth = 1.0 - fDepth;
|
||||
#endif
|
||||
|
||||
if (fDepth <= vSplitPoints.x)
|
||||
{
|
||||
SGX_ShadowPCF4(shadowMap0, lightPosition0, invShadowMapSize0, oShadowFactor);
|
||||
#ifdef DEBUG_PSSM
|
||||
oDiffuse.r += 1.0;
|
||||
#endif
|
||||
}
|
||||
#if PSSM_NUM_SPLITS > 2
|
||||
else if (fDepth <= vSplitPoints.y)
|
||||
{
|
||||
SGX_ShadowPCF4(shadowMap1, lightPosition1, invShadowMapSize1, oShadowFactor);
|
||||
#ifdef DEBUG_PSSM
|
||||
oDiffuse.g += 1.0;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#if PSSM_NUM_SPLITS > 3
|
||||
else if (fDepth <= vSplitPoints.z)
|
||||
{
|
||||
SGX_ShadowPCF4(shadowMap2, lightPosition2, invShadowMapSize2, oShadowFactor);
|
||||
#ifdef DEBUG_PSSM
|
||||
oDiffuse.r += 1.0;
|
||||
oDiffuse.g += 1.0;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
else if (fDepth <= vSplitPoints.w)
|
||||
{
|
||||
SGX_ShadowPCF4(shadowMap3, lightPosition3, invShadowMapSize3, oShadowFactor);
|
||||
#ifdef DEBUG_PSSM
|
||||
oDiffuse.b += 1.0;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
// behind far distance
|
||||
oShadowFactor = 1.0;
|
||||
}
|
||||
}
|
||||
825
resources/shaderlib/SGXLib_LayeredBlending.glsl
Normal file
@@ -0,0 +1,825 @@
|
||||
/*
|
||||
** layered blending & misc math
|
||||
** Blending modes, RGB/HSL/Contrast/Desaturate, levels control
|
||||
**
|
||||
** The shaders below are base on the shaders created by:
|
||||
** Romain Dura | Romz
|
||||
** Blog: http://blog.mouaif.org
|
||||
** Post: http://blog.mouaif.org/?p=94
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
** Desaturation
|
||||
*/
|
||||
|
||||
vec4 Desaturate(in vec3 color, in float Desaturation)
|
||||
{
|
||||
vec3 grayXfer = vec3(0.3, 0.59, 0.11);
|
||||
float grayf = dot(grayXfer, color);
|
||||
vec3 gray = vec3(grayf, grayf, grayf);
|
||||
return vec4(mix(color, gray, Desaturation), 1.0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Hue, saturation, luminance
|
||||
*/
|
||||
|
||||
vec3 RGBToHSL(in vec3 color)
|
||||
{
|
||||
vec3 hsl; // init to 0 to avoid warnings ? (and reverse if + remove first part)
|
||||
|
||||
float fmin = min(min(color.r, color.g), color.b); //Min. value of RGB
|
||||
float fmax = max(max(color.r, color.g), color.b); //Max. value of RGB
|
||||
float delta = fmax - fmin; //Delta RGB value
|
||||
|
||||
hsl.z = (fmax + fmin) / 2.0; // Luminance
|
||||
|
||||
if (delta == 0.0) //This is a gray, no chroma...
|
||||
{
|
||||
hsl.x = 0.0; // Hue
|
||||
hsl.y = 0.0; // Saturation
|
||||
}
|
||||
else //Chromatic data...
|
||||
{
|
||||
if (hsl.z < 0.5)
|
||||
hsl.y = delta / (fmax + fmin); // Saturation
|
||||
else
|
||||
hsl.y = delta / (2.0 - fmax - fmin); // Saturation
|
||||
|
||||
float deltaR = (((fmax - color.r) / 6.0) + (delta / 2.0)) / delta;
|
||||
float deltaG = (((fmax - color.g) / 6.0) + (delta / 2.0)) / delta;
|
||||
float deltaB = (((fmax - color.b) / 6.0) + (delta / 2.0)) / delta;
|
||||
|
||||
if (color.r == fmax )
|
||||
hsl.x = deltaB - deltaG; // Hue
|
||||
else if (color.g == fmax)
|
||||
hsl.x = (1.0 / 3.0) + deltaR - deltaB; // Hue
|
||||
else if (color.b == fmax)
|
||||
hsl.x = (2.0 / 3.0) + deltaG - deltaR; // Hue
|
||||
|
||||
if (hsl.x < 0.0)
|
||||
hsl.x += 1.0; // Hue
|
||||
else if (hsl.x > 1.0)
|
||||
hsl.x -= 1.0; // Hue
|
||||
}
|
||||
|
||||
return hsl;
|
||||
}
|
||||
|
||||
float HueToRGB(in float f1, in float f2, in float hue)
|
||||
{
|
||||
if (hue < 0.0)
|
||||
hue += 1.0;
|
||||
else if (hue > 1.0)
|
||||
hue -= 1.0;
|
||||
float res;
|
||||
if ((6.0 * hue) < 1.0)
|
||||
res = f1 + (f2 - f1) * 6.0 * hue;
|
||||
else if ((2.0 * hue) < 1.0)
|
||||
res = f2;
|
||||
else if ((3.0 * hue) < 2.0)
|
||||
res = f1 + (f2 - f1) * ((2.0 / 3.0) - hue) * 6.0;
|
||||
else
|
||||
res = f1;
|
||||
return res;
|
||||
}
|
||||
|
||||
vec3 HSLToRGB(in vec3 hsl)
|
||||
{
|
||||
vec3 rgb;
|
||||
|
||||
if (hsl.y == 0.0)
|
||||
rgb = hsl.zzz; // Luminance
|
||||
else
|
||||
{
|
||||
float f2;
|
||||
|
||||
if (hsl.z < 0.5)
|
||||
f2 = hsl.z * (1.0 + hsl.y);
|
||||
else
|
||||
f2 = (hsl.z + hsl.y) - (hsl.y * hsl.z);
|
||||
|
||||
float f1 = 2.0 * hsl.z - f2;
|
||||
|
||||
rgb.r = HueToRGB(f1, f2, hsl.x + (1.0/3.0));
|
||||
rgb.g = HueToRGB(f1, f2, hsl.x);
|
||||
rgb.b = HueToRGB(f1, f2, hsl.x - (1.0/3.0));
|
||||
}
|
||||
|
||||
return rgb;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Contrast, saturation, brightness
|
||||
** Code of this function is from TGM's shader pack
|
||||
** http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=21057
|
||||
*/
|
||||
|
||||
// For all settings: 1.0 = 100% 0.5=50% 1.5 = 150%
|
||||
vec3 ContrastSaturationBrightness(in vec3 color, in float brt, in float sat, in float con)
|
||||
{
|
||||
// Increase or decrease these values to adjust r, g and b color channels separately
|
||||
const float AvgLumR = 0.5;
|
||||
const float AvgLumG = 0.5;
|
||||
const float AvgLumB = 0.5;
|
||||
|
||||
const vec3 LumCoeff = vec3(0.2125, 0.7154, 0.0721);
|
||||
|
||||
vec3 AvgLumin = vec3(AvgLumR, AvgLumG, AvgLumB);
|
||||
vec3 brtColor = color * brt;
|
||||
float intensityf = dot(brtColor, LumCoeff);
|
||||
vec3 intensity = vec3(intensityf, intensityf, intensityf);
|
||||
vec3 satColor = mix(intensity, brtColor, sat);
|
||||
vec3 conColor = mix(AvgLumin, satColor, con);
|
||||
return conColor;
|
||||
}
|
||||
|
||||
/*
|
||||
** Float blending modes
|
||||
** Adapted from here: http://www.nathanm.com/photoshop-blending-math/
|
||||
** But I modified the HardMix (wrong condition), Overlay, SoftLight, ColorDodge, ColorBurn, VividLight, PinLight (inverted layers) ones to have correct results
|
||||
*/
|
||||
|
||||
#define BlendLinearDodgef BlendAddf
|
||||
#define BlendLinearBurnf BlendSubtractf
|
||||
#define BlendAddf(base, blend) min(base + blend, 1.0)
|
||||
#define BlendSubtractf(base, blend) max(base + blend - 1.0, 0.0)
|
||||
#define BlendLightenf(base, blend) max(blend, base)
|
||||
#define BlendDarkenf(base, blend) min(blend, base)
|
||||
#define BlendScreenf(base, blend) (1.0 - ((1.0 - base) * (1.0 - blend)))
|
||||
#define BlendOverlayf(base, blend) (base < 0.5 ? (2.0 * base * blend) : (1.0 - 2.0 * (1.0 - base) * (1.0 - blend)))
|
||||
#define BlendSoftLightf(base, blend) ((blend < 0.5) ? (2.0 * base * blend + base * base * (1.0 - 2.0 * blend)) : (sqrt(base) * (2.0 * blend - 1.0) + 2.0 * base * (1.0 - blend)))
|
||||
#define BlendColorDodgef(base, blend) ((blend == 1.0) ? blend : min(base / (1.0 - blend), 1.0))
|
||||
#define BlendColorBurnf(base, blend) ((blend == 0.0) ? blend : max((1.0 - ((1.0 - base) / blend)), 0.0))
|
||||
#define BlendHardMixf(base, blend) ((BlendVividLightf(base, blend) < 0.5) ? 0.0 : 1.0)
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** Vector3 blending modes
|
||||
*/
|
||||
|
||||
// Component wise blending
|
||||
#define Blend1(base, blend, funcf) funcf(base, blend)
|
||||
#define Blend3(base, blend, funcf) vec3(funcf(base.r, blend.r), funcf(base.g, blend.g), funcf(base.b, blend.b))
|
||||
#define Blend4(base, blend, funcf) vec4(funcf(base.r, blend.r), funcf(base.g, blend.g), funcf(base.b, blend.b), funcf(base.a, blend.a))
|
||||
|
||||
#define BlendNormal(base, blend) (base)
|
||||
#define BlendMultiply(base, blend) (base * blend)
|
||||
#define BlendAverage(base, blend) ((base + blend) / 2.0)
|
||||
#define BlendAdd(base, blend) min(base + blend, 1.0)
|
||||
#define BlendSubtract(base, blend) max(base + blend - 1.0, 0.0)
|
||||
#define BlendDifference(base, blend) abs(base - blend)
|
||||
#define BlendNegation(base, blend) (1.0 - abs(1.0 - base - blend))
|
||||
#define BlendExclusion(base, blend) (base + blend - 2.0 * base * blend)
|
||||
#define BlendPhoenix(base, blend) (min(base, blend) - max(base, blend) + 1.0)
|
||||
#define BlendOpacity(base, blend, F, O) (F(base, blend) * O + blend * (1.0 - O))
|
||||
|
||||
// Hue Blend mode creates the result color by combining the luminance and saturation of the base color with the hue of the blend color.
|
||||
float BlendHue1(in float base, in float blend)
|
||||
{
|
||||
return base;
|
||||
}
|
||||
|
||||
vec3 BlendHue3(in vec3 base, in vec3 blend)
|
||||
{
|
||||
vec3 baseHSL = RGBToHSL(base);
|
||||
return HSLToRGB(vec3(RGBToHSL(blend).r, baseHSL.g, baseHSL.b));
|
||||
}
|
||||
|
||||
vec4 BlendHue4(in vec4 base, in vec4 blend)
|
||||
{
|
||||
vec3 hue = BlendHue3(base.xyz, blend.xyz);
|
||||
return vec4(hue.x, hue.y, hue.z, BlendHue1(base.w, blend.w));
|
||||
}
|
||||
|
||||
// Saturation Blend mode creates the result color by combining the luminance and hue of the base color with the saturation of the blend color.
|
||||
float BlendSaturation1(in float base, in float blend)
|
||||
{
|
||||
return base;
|
||||
}
|
||||
|
||||
vec3 BlendSaturation3(in vec3 base, in vec3 blend)
|
||||
{
|
||||
vec3 baseHSL = RGBToHSL(base);
|
||||
return HSLToRGB(vec3(baseHSL.r, RGBToHSL(blend).g, baseHSL.b));
|
||||
}
|
||||
|
||||
vec4 BlendSaturation4(in vec4 base, in vec4 blend)
|
||||
{
|
||||
vec3 hue = BlendSaturation3(base.xyz, blend.xyz);
|
||||
return vec4(hue.x, hue.y, hue.z, BlendSaturation1(base.w, blend.w));
|
||||
}
|
||||
|
||||
// Color Mode keeps the brightness of the base color and applies both the hue and saturation of the blend color.
|
||||
float BlendColor1(in float base, in float blend)
|
||||
{
|
||||
return base;
|
||||
}
|
||||
|
||||
vec3 BlendColor3(in vec3 base, in vec3 blend)
|
||||
{
|
||||
vec3 blendHSL = RGBToHSL(blend);
|
||||
return HSLToRGB(vec3(blendHSL.r, blendHSL.g, RGBToHSL(base).b));
|
||||
}
|
||||
|
||||
vec4 BlendColor4(in vec4 base, in vec4 blend)
|
||||
{
|
||||
vec3 hue = BlendColor3(base.xyz, blend.xyz);
|
||||
return vec4(hue.x, hue.y, hue.z, BlendColor1(base.w, blend.w));
|
||||
}
|
||||
|
||||
|
||||
// Luminosity Blend mode creates the result color by combining the hue and saturation of the base color with the luminance of the blend color.
|
||||
float BlendLuminosity1(in float base, in float blend)
|
||||
{
|
||||
return base;
|
||||
}
|
||||
|
||||
vec3 BlendLuminosity3(in vec3 base, in vec3 blend)
|
||||
{
|
||||
vec3 baseHSL = RGBToHSL(base);
|
||||
return HSLToRGB(vec3(baseHSL.r, baseHSL.g, RGBToHSL(blend).b));
|
||||
}
|
||||
|
||||
vec4 BlendLuminosity4(in vec4 base, in vec4 blend)
|
||||
{
|
||||
vec3 hue = BlendLuminosity3(base.xyz, blend.xyz);
|
||||
return vec4(hue.x, hue.y, hue.z, BlendLuminosity1(base.w, blend.w));
|
||||
}
|
||||
|
||||
float BlendLinearLightf(in float s1, in float s2)
|
||||
{
|
||||
float oColor;
|
||||
|
||||
if (s2 < 0.5)
|
||||
{
|
||||
float s2x = (2.0 * s2);
|
||||
oColor = BlendSubtractf(s1, s2x);
|
||||
}
|
||||
else
|
||||
{
|
||||
float s2x = (2.0 * (s2 - 0.5));
|
||||
oColor = BlendAddf(s1, s2x);
|
||||
}
|
||||
|
||||
return oColor;
|
||||
}
|
||||
|
||||
float BlendVividLightf(in float s1, in float s2)
|
||||
{
|
||||
float oColor;
|
||||
|
||||
if (s2 < 0.5)
|
||||
{
|
||||
float s2x = (2.0 * s2);
|
||||
oColor = BlendColorBurnf(s1, s2x);
|
||||
}
|
||||
else
|
||||
{
|
||||
float s2x = (2.0 * (s2 - 0.5));
|
||||
oColor = BlendColorDodgef(s1, s2x);
|
||||
}
|
||||
|
||||
return oColor;
|
||||
}
|
||||
|
||||
float BlendPinLightf(in float s1, in float s2)
|
||||
{
|
||||
float oColor;
|
||||
|
||||
if (s2 < 0.5)
|
||||
{
|
||||
float s2x = (2.0 * s2);
|
||||
oColor = BlendDarkenf(s1, s2x);
|
||||
}
|
||||
else
|
||||
{
|
||||
float s2x = (2.0 * (s2 - 0.5));
|
||||
oColor = BlendLightenf(s1, s2x);
|
||||
}
|
||||
|
||||
return oColor;
|
||||
}
|
||||
|
||||
float BlendReflectf(in float s1, in float s2)
|
||||
{
|
||||
float oColor;
|
||||
|
||||
if (s2 == 1.0)
|
||||
{
|
||||
oColor = s2;
|
||||
}
|
||||
else
|
||||
{
|
||||
float s1x = (s1 * s1) / (1.0 - s2);
|
||||
|
||||
oColor = min(s1x, 1.0);
|
||||
}
|
||||
|
||||
return oColor;
|
||||
}
|
||||
|
||||
//------------------------------------
|
||||
// Interface for RTShader
|
||||
//------------------------------------
|
||||
|
||||
|
||||
void SGX_blend_normal(in vec4 basePixel, in vec4 blendPixel, out vec4 oColor)
|
||||
{
|
||||
oColor = BlendNormal(basePixel, blendPixel);
|
||||
}
|
||||
|
||||
void SGX_blend_normal(in vec3 basePixel, in vec3 blendPixel, out vec3 oColor)
|
||||
{
|
||||
oColor = BlendNormal(basePixel, blendPixel);
|
||||
}
|
||||
|
||||
void SGX_blend_normal(in float basePixel, in float blendPixel, out float oColor)
|
||||
{
|
||||
oColor = BlendNormal(basePixel, blendPixel);
|
||||
}
|
||||
|
||||
|
||||
void SGX_blend_lighten(in vec4 basePixel, in vec4 blendPixel, out vec4 oColor)
|
||||
{
|
||||
oColor = BlendLightenf(basePixel, blendPixel);
|
||||
}
|
||||
|
||||
void SGX_blend_lighten(in vec3 basePixel, in vec3 blendPixel, out vec3 oColor)
|
||||
{
|
||||
oColor = BlendLightenf(basePixel, blendPixel);
|
||||
}
|
||||
|
||||
void SGX_blend_lighten(in float basePixel, in float blendPixel, out float oColor)
|
||||
{
|
||||
oColor = BlendLightenf(basePixel, blendPixel);
|
||||
}
|
||||
|
||||
|
||||
void SGX_blend_darken(in vec4 basePixel, in vec4 blendPixel, out vec4 oColor)
|
||||
{
|
||||
oColor = BlendDarkenf(basePixel, blendPixel);
|
||||
}
|
||||
|
||||
void SGX_blend_darken(in vec3 basePixel, in vec3 blendPixel, out vec3 oColor)
|
||||
{
|
||||
oColor = BlendDarkenf(basePixel, blendPixel);
|
||||
}
|
||||
|
||||
void SGX_blend_darken(in float basePixel, in float blendPixel, out float oColor)
|
||||
{
|
||||
oColor = BlendDarkenf(basePixel, blendPixel);
|
||||
}
|
||||
|
||||
|
||||
void SGX_blend_multiply(in vec4 basePixel, in vec4 blendPixel, out vec4 oColor)
|
||||
{
|
||||
oColor = BlendMultiply(basePixel, blendPixel);
|
||||
}
|
||||
|
||||
void SGX_blend_multiply(in vec3 basePixel, in vec3 blendPixel, out vec3 oColor)
|
||||
{
|
||||
oColor = BlendMultiply(basePixel, blendPixel);
|
||||
}
|
||||
|
||||
void SGX_blend_multiply(in float basePixel, in float blendPixel, out float oColor)
|
||||
{
|
||||
oColor = BlendMultiply(basePixel, blendPixel);
|
||||
}
|
||||
|
||||
|
||||
void SGX_blend_average(in vec4 basePixel, in vec4 blendPixel, out vec4 oColor)
|
||||
{
|
||||
oColor = BlendAverage(basePixel, blendPixel);
|
||||
}
|
||||
|
||||
void SGX_blend_average(in vec3 basePixel, in vec3 blendPixel, out vec3 oColor)
|
||||
{
|
||||
oColor = BlendAverage(basePixel, blendPixel);
|
||||
}
|
||||
|
||||
void SGX_blend_average(in float basePixel, in float blendPixel, out float oColor)
|
||||
{
|
||||
oColor = BlendAverage(basePixel, blendPixel);
|
||||
}
|
||||
|
||||
|
||||
void SGX_blend_add(in vec4 basePixel, in vec4 blendPixel, out vec4 oColor)
|
||||
{
|
||||
oColor = BlendAdd(basePixel, blendPixel);
|
||||
}
|
||||
|
||||
void SGX_blend_add(in vec3 basePixel, in vec3 blendPixel, out vec3 oColor)
|
||||
{
|
||||
oColor = BlendAdd(basePixel, blendPixel);
|
||||
}
|
||||
|
||||
void SGX_blend_add(in float basePixel, in float blendPixel, out float oColor)
|
||||
{
|
||||
oColor = BlendAdd(basePixel, blendPixel);
|
||||
}
|
||||
|
||||
|
||||
void SGX_blend_subtract(in vec4 basePixel, in vec4 blendPixel, out vec4 oColor)
|
||||
{
|
||||
oColor = BlendSubtract(basePixel, blendPixel);
|
||||
}
|
||||
|
||||
void SGX_blend_subtract(in vec3 basePixel, in vec3 blendPixel, out vec3 oColor)
|
||||
{
|
||||
oColor = BlendSubtract(basePixel, blendPixel);
|
||||
}
|
||||
|
||||
void SGX_blend_subtract(in float basePixel, in float blendPixel, out float oColor)
|
||||
{
|
||||
oColor = BlendSubtract(basePixel, blendPixel);
|
||||
}
|
||||
|
||||
|
||||
void SGX_blend_difference(in vec4 basePixel, in vec4 blendPixel, out vec4 oColor)
|
||||
{
|
||||
oColor = BlendDifference(basePixel, blendPixel);
|
||||
}
|
||||
void SGX_blend_difference(in vec3 basePixel, in vec3 blendPixel, out vec3 oColor)
|
||||
{
|
||||
oColor = BlendDifference(basePixel, blendPixel);
|
||||
}
|
||||
void SGX_blend_difference(in float basePixel, in float blendPixel, out float oColor)
|
||||
{
|
||||
oColor = BlendDifference(basePixel, blendPixel);
|
||||
}
|
||||
|
||||
|
||||
void SGX_blend_negation(in vec4 basePixel, in vec4 blendPixel, out vec4 oColor)
|
||||
{
|
||||
oColor = BlendNegation(basePixel, blendPixel);
|
||||
}
|
||||
void SGX_blend_negation(in vec3 basePixel, in vec3 blendPixel, out vec3 oColor)
|
||||
{
|
||||
oColor = BlendNegation(basePixel, blendPixel);
|
||||
}
|
||||
void SGX_blend_negation(in float basePixel, in float blendPixel, out float oColor)
|
||||
{
|
||||
oColor = BlendNegation(basePixel, blendPixel);
|
||||
}
|
||||
|
||||
|
||||
void SGX_blend_exclusion(in vec4 basePixel, in vec4 blendPixel, out vec4 oColor)
|
||||
{
|
||||
oColor = BlendExclusion(basePixel, blendPixel);
|
||||
}
|
||||
void SGX_blend_exclusion(in vec3 basePixel, in vec3 blendPixel, out vec3 oColor)
|
||||
{
|
||||
oColor = BlendExclusion(basePixel, blendPixel);
|
||||
}
|
||||
void SGX_blend_exclusion(in float basePixel, in float blendPixel, out float oColor)
|
||||
{
|
||||
oColor = BlendExclusion(basePixel, blendPixel);
|
||||
}
|
||||
|
||||
|
||||
void SGX_blend_screen(in vec4 s1, in vec4 s2, out vec4 oColor)
|
||||
{
|
||||
oColor = vec4(BlendScreenf(s1.r, s2.r),
|
||||
BlendScreenf(s1.g, s2.g),
|
||||
BlendScreenf(s1.b, s2.b),
|
||||
BlendScreenf(s1.a, s2.a));
|
||||
}
|
||||
void SGX_blend_screen(in vec3 s1, in vec3 s2, out vec3 oColor)
|
||||
{
|
||||
oColor = vec3(BlendScreenf(s1.r, s2.r),
|
||||
BlendScreenf(s1.g, s2.g),
|
||||
BlendScreenf(s1.b, s2.b));
|
||||
}
|
||||
void SGX_blend_screen(in float s1, in float s2, out float oColor)
|
||||
{
|
||||
oColor = BlendScreenf(s1, s2);
|
||||
}
|
||||
|
||||
|
||||
void SGX_blend_overlay(in vec4 s1, in vec4 s2, out vec4 oColor)
|
||||
{
|
||||
oColor = vec4(BlendOverlayf(s1.r, s2.r),
|
||||
BlendOverlayf(s1.g, s2.g),
|
||||
BlendOverlayf(s1.b, s2.b),
|
||||
BlendOverlayf(s1.a, s2.a));
|
||||
}
|
||||
void SGX_blend_overlay(in vec3 s1, in vec3 s2, out vec3 oColor)
|
||||
{
|
||||
oColor = vec3(BlendOverlayf(s1.r, s2.r),
|
||||
BlendOverlayf(s1.g, s2.g),
|
||||
BlendOverlayf(s1.b, s2.b));
|
||||
}
|
||||
void SGX_blend_overlay(in float s1, in float s2, out float oColor)
|
||||
{
|
||||
oColor = BlendOverlayf(s1, s2);
|
||||
}
|
||||
|
||||
|
||||
void SGX_blend_softLight(in vec4 s1, in vec4 s2, out vec4 oColor)
|
||||
{
|
||||
oColor = vec4(BlendSoftLightf(s1.r, s2.r),
|
||||
BlendSoftLightf(s1.g, s2.g),
|
||||
BlendSoftLightf(s1.b, s2.b),
|
||||
BlendSoftLightf(s1.a, s2.a));
|
||||
}
|
||||
void SGX_blend_softLight(in vec3 s1, in vec3 s2, out vec3 oColor)
|
||||
{
|
||||
oColor = vec3(BlendSoftLightf(s1.r, s2.r),
|
||||
BlendSoftLightf(s1.g, s2.g),
|
||||
BlendSoftLightf(s1.b, s2.b));
|
||||
}
|
||||
void SGX_blend_softLight(in float s1, in float s2, out float oColor)
|
||||
{
|
||||
oColor = BlendSoftLightf(s1, s2);
|
||||
}
|
||||
|
||||
|
||||
void SGX_blend_hardLight(in vec4 s1, in vec4 s2, out vec4 oColor)
|
||||
{
|
||||
oColor = vec4(BlendOverlayf(s1.r, s2.r),
|
||||
BlendOverlayf(s1.g, s2.g),
|
||||
BlendOverlayf(s1.b, s2.b),
|
||||
BlendOverlayf(s1.a, s2.a));
|
||||
}
|
||||
void SGX_blend_hardLight(in vec3 s1, in vec3 s2, out vec3 oColor)
|
||||
{
|
||||
oColor = vec3(BlendOverlayf(s1.r, s2.r),
|
||||
BlendOverlayf(s1.g, s2.g),
|
||||
BlendOverlayf(s1.b, s2.b));
|
||||
}
|
||||
void SGX_blend_hardLight(in float s1, in float s2, out float oColor)
|
||||
{
|
||||
oColor = BlendOverlayf(s1, s2);
|
||||
}
|
||||
|
||||
|
||||
void SGX_blend_colorDodge(in vec4 s1, in vec4 s2, out vec4 oColor)
|
||||
{
|
||||
oColor = vec4(BlendColorDodgef(s1.r, s2.r),
|
||||
BlendColorDodgef(s1.g, s2.g),
|
||||
BlendColorDodgef(s1.b, s2.b),
|
||||
BlendColorDodgef(s1.a, s2.a));
|
||||
}
|
||||
void SGX_blend_colorDodge(in vec3 s1, in vec3 s2, out vec3 oColor)
|
||||
{
|
||||
oColor = vec3(BlendColorDodgef(s1.r, s2.r),
|
||||
BlendColorDodgef(s1.g, s2.g),
|
||||
BlendColorDodgef(s1.b, s2.b));
|
||||
}
|
||||
void SGX_blend_colorDodge(in float s1, in float s2, out float oColor)
|
||||
{
|
||||
oColor = BlendColorDodgef(s1, s2);
|
||||
}
|
||||
|
||||
|
||||
void SGX_blend_colorBurn(in vec4 s1, in vec4 s2, out vec4 oColor)
|
||||
{
|
||||
oColor = vec4(BlendColorBurnf(s1.r, s2.r),
|
||||
BlendColorBurnf(s1.g, s2.g),
|
||||
BlendColorBurnf(s1.b, s2.b),
|
||||
BlendColorBurnf(s1.a, s2.a));
|
||||
}
|
||||
void SGX_blend_colorBurn(in vec3 s1, in vec3 s2, out vec3 oColor)
|
||||
{
|
||||
oColor = vec3(BlendColorBurnf(s1.r, s2.r),
|
||||
BlendColorBurnf(s1.g, s2.g),
|
||||
BlendColorBurnf(s1.b, s2.b));
|
||||
}
|
||||
void SGX_blend_colorBurn(in float s1, in float s2, out float oColor)
|
||||
{
|
||||
oColor = BlendColorBurnf(s1, s2);
|
||||
}
|
||||
|
||||
|
||||
void SGX_blend_linearDodge(in vec4 basePixel, in vec4 blendPixel, out vec4 oColor)
|
||||
{
|
||||
oColor = BlendAddf(basePixel, blendPixel);
|
||||
}
|
||||
void SGX_blend_linearDodge(in vec3 basePixel, in vec3 blendPixel, out vec3 oColor)
|
||||
{
|
||||
oColor = BlendAddf(basePixel, blendPixel);
|
||||
}
|
||||
void SGX_blend_linearDodge(in float basePixel, in float blendPixel, out float oColor)
|
||||
{
|
||||
oColor = BlendAddf(basePixel, blendPixel);
|
||||
}
|
||||
|
||||
|
||||
void SGX_blend_linearBurn(in vec4 basePixel, in vec4 blendPixel, out vec4 oColor)
|
||||
{
|
||||
oColor = BlendSubtractf(basePixel, blendPixel);
|
||||
}
|
||||
void SGX_blend_linearBurn(in vec3 basePixel, in vec3 blendPixel, out vec3 oColor)
|
||||
{
|
||||
oColor = BlendSubtractf(basePixel, blendPixel);
|
||||
}
|
||||
void SGX_blend_linearBurn(in float basePixel, in float blendPixel, out float oColor)
|
||||
{
|
||||
oColor = BlendSubtractf(basePixel, blendPixel);
|
||||
}
|
||||
|
||||
|
||||
void SGX_blend_linearLight(in vec4 s1, in vec4 s2, out vec4 oColor)
|
||||
{
|
||||
oColor = vec4(BlendLinearLightf(s1.r, s2.r),
|
||||
BlendLinearLightf(s1.g, s2.g),
|
||||
BlendLinearLightf(s1.b, s2.b),
|
||||
BlendLinearLightf(s1.a, s2.a));
|
||||
}
|
||||
void SGX_blend_linearLight(in vec3 s1, in vec3 s2, out vec3 oColor)
|
||||
{
|
||||
oColor = vec3(BlendLinearLightf(s1.r, s2.r),
|
||||
BlendLinearLightf(s1.g, s2.g),
|
||||
BlendLinearLightf(s1.b, s2.b));
|
||||
}
|
||||
void SGX_blend_linearLight(in float s1, in float s2, out float oColor)
|
||||
{
|
||||
oColor = BlendLinearLightf(s1, s2);
|
||||
}
|
||||
|
||||
|
||||
void SGX_blend_vividLight(in vec4 s1, in vec4 s2, out vec4 oColor)
|
||||
{
|
||||
oColor = vec4(BlendVividLightf(s1.r, s2.r),
|
||||
BlendVividLightf(s1.g, s2.g),
|
||||
BlendVividLightf(s1.b, s2.b),
|
||||
BlendVividLightf(s1.a, s2.a));
|
||||
}
|
||||
void SGX_blend_vividLight(in vec3 s1, in vec3 s2, out vec3 oColor)
|
||||
{
|
||||
oColor = vec3(BlendVividLightf(s1.r, s2.r),
|
||||
BlendVividLightf(s1.g, s2.g),
|
||||
BlendVividLightf(s1.b, s2.b));
|
||||
}
|
||||
void SGX_blend_vividLight(in float s1, in float s2, out float oColor)
|
||||
{
|
||||
oColor = BlendVividLightf(s1, s2);
|
||||
}
|
||||
|
||||
|
||||
void SGX_blend_pinLight(in vec4 s1, in vec4 s2, out vec4 oColor)
|
||||
{
|
||||
oColor = vec4(BlendPinLightf(s1.r, s2.r),
|
||||
BlendPinLightf(s1.g, s2.g),
|
||||
BlendPinLightf(s1.b, s2.b),
|
||||
BlendPinLightf(s1.a, s2.a));
|
||||
}
|
||||
void SGX_blend_pinLight(in vec3 s1, in vec3 s2, out vec3 oColor)
|
||||
{
|
||||
oColor = vec3(BlendPinLightf(s1.r, s2.r),
|
||||
BlendPinLightf(s1.g, s2.g),
|
||||
BlendPinLightf(s1.b, s2.b));
|
||||
}
|
||||
void SGX_blend_pinLight(in float s1, in float s2, out float oColor)
|
||||
{
|
||||
oColor = BlendPinLightf(s1, s2);
|
||||
}
|
||||
|
||||
|
||||
void SGX_blend_hardMix(in vec4 s1, in vec4 s2, out vec4 oColor)
|
||||
{
|
||||
oColor = vec4(BlendHardMixf(s1.r, s2.r),
|
||||
BlendHardMixf(s1.g, s2.g),
|
||||
BlendHardMixf(s1.b, s2.b),
|
||||
BlendHardMixf(s1.a, s2.a));
|
||||
}
|
||||
void SGX_blend_hardMix(in vec3 s1, in vec3 s2, out vec3 oColor)
|
||||
{
|
||||
oColor = vec3(BlendHardMixf(s1.r, s2.r),
|
||||
BlendHardMixf(s1.g, s2.g),
|
||||
BlendHardMixf(s1.b, s2.b));
|
||||
}
|
||||
void SGX_blend_hardMix(in float s1, in float s2, out float oColor)
|
||||
{
|
||||
oColor = BlendHardMixf(s1, s2);
|
||||
}
|
||||
|
||||
void SGX_blend_reflect(in vec4 s1, in vec4 s2, out vec4 oColor)
|
||||
{
|
||||
oColor = vec4(BlendReflectf(s1.r, s2.r),
|
||||
BlendReflectf(s1.g, s2.g),
|
||||
BlendReflectf(s1.b, s2.b),
|
||||
BlendReflectf(s1.a, s2.a));
|
||||
}
|
||||
void SGX_blend_reflect(in vec3 s1, in vec3 s2, out vec3 oColor)
|
||||
{
|
||||
oColor = vec3(BlendReflectf(s1.r, s2.r),
|
||||
BlendReflectf(s1.g, s2.g),
|
||||
BlendReflectf(s1.b, s2.b));
|
||||
}
|
||||
void SGX_blend_reflect(in float s1, in float s2, out float oColor)
|
||||
{
|
||||
oColor = BlendReflectf(s1, s2);
|
||||
}
|
||||
|
||||
|
||||
void SGX_blend_glow(in vec4 s1, in vec4 s2, out vec4 oColor)
|
||||
{
|
||||
oColor = vec4(BlendReflectf(s1.r, s2.r),
|
||||
BlendReflectf(s1.g, s2.g),
|
||||
BlendReflectf(s1.b, s2.b),
|
||||
BlendReflectf(s1.a, s2.a));
|
||||
}
|
||||
void SGX_blend_glow(in vec3 s1, in vec3 s2, out vec3 oColor)
|
||||
{
|
||||
oColor = vec3(BlendReflectf(s1.r, s2.r),
|
||||
BlendReflectf(s1.g, s2.g),
|
||||
BlendReflectf(s1.b, s2.b));
|
||||
}
|
||||
void SGX_blend_glow(in float s1, in float s2, out float oColor)
|
||||
{
|
||||
oColor = BlendReflectf(s1, s2);
|
||||
}
|
||||
|
||||
|
||||
void SGX_blend_phoenix(in vec4 basePixel, in vec4 blendPixel, out vec4 oColor)
|
||||
{
|
||||
oColor = BlendPhoenix(basePixel, blendPixel);
|
||||
}
|
||||
void SGX_blend_phoenix(in vec3 basePixel, in vec3 blendPixel, out vec3 oColor)
|
||||
{
|
||||
oColor = BlendPhoenix(basePixel, blendPixel);
|
||||
}
|
||||
void SGX_blend_phoenix(in float basePixel, in float blendPixel, out float oColor)
|
||||
{
|
||||
oColor = BlendPhoenix(basePixel, blendPixel);
|
||||
}
|
||||
|
||||
|
||||
void SGX_blend_saturation(in vec4 basePixel, in vec4 blendPixel, out vec4 oColor)
|
||||
{
|
||||
oColor = BlendSaturation4(basePixel, blendPixel);
|
||||
}
|
||||
void SGX_blend_saturation(in vec3 basePixel, in vec3 blendPixel, out vec3 oColor)
|
||||
{
|
||||
oColor = BlendSaturation3(basePixel, blendPixel);
|
||||
}
|
||||
void SGX_blend_saturation(in float basePixel, in float blendPixel, out float oColor)
|
||||
{
|
||||
oColor = BlendSaturation1(basePixel, blendPixel);
|
||||
}
|
||||
|
||||
|
||||
void SGX_blend_color(in vec4 basePixel, in vec4 blendPixel, out vec4 oColor)
|
||||
{
|
||||
oColor = BlendColor4(basePixel, blendPixel);
|
||||
}
|
||||
void SGX_blend_color(in vec3 basePixel, in vec3 blendPixel, out vec3 oColor)
|
||||
{
|
||||
oColor = BlendColor3(basePixel, blendPixel);
|
||||
}
|
||||
void SGX_blend_color(in float basePixel, in float blendPixel, out float oColor)
|
||||
{
|
||||
oColor = BlendColor1(basePixel, blendPixel);
|
||||
}
|
||||
|
||||
|
||||
void SGX_blend_luminosity(in vec4 basePixel, in vec4 blendPixel, out vec4 oColor)
|
||||
{
|
||||
oColor = BlendLuminosity4(basePixel, blendPixel);
|
||||
}
|
||||
void SGX_blend_luminosity(in vec3 basePixel, in vec3 blendPixel, out vec3 oColor)
|
||||
{
|
||||
oColor = BlendLuminosity3(basePixel, blendPixel);
|
||||
}
|
||||
void SGX_blend_luminosity(in float basePixel, in float blendPixel, out float oColor)
|
||||
{
|
||||
oColor = BlendLuminosity1(basePixel, blendPixel);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Source modification functions
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
void SGX_src_mod_modulate(in vec4 iColor, in vec4 controlVal, out vec4 oColor)
|
||||
{
|
||||
oColor = iColor * controlVal;
|
||||
}
|
||||
void SGX_src_mod_modulate(in vec3 iColor, in vec3 controlVal, out vec3 oColor)
|
||||
{
|
||||
oColor = iColor * controlVal;
|
||||
}
|
||||
void SGX_src_mod_modulate(in float iColor, in float controlVal, out float oColor)
|
||||
{
|
||||
oColor = iColor * controlVal;
|
||||
}
|
||||
|
||||
void SGX_src_mod_inv_modulate(in vec4 iColor, in vec4 controlVal, out vec4 oColor)
|
||||
{
|
||||
oColor = mix(iColor, vec4(1.0,1.0,1.0,1.0), controlVal);
|
||||
}
|
||||
void SGX_src_mod_inv_modulate(in vec3 iColor, in vec3 controlVal, out vec3 oColor)
|
||||
{
|
||||
oColor = mix(iColor, vec3(1.0,1.0,1.0), controlVal);
|
||||
}
|
||||
void SGX_src_mod_inv_modulate(in float iColor, in float controlVal, out float oColor)
|
||||
{
|
||||
oColor = mix(iColor, 1.0, controlVal);
|
||||
}
|
||||
125
resources/shaderlib/SGXLib_NormalMap.glsl
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
-----------------------------------------------------------------------------
|
||||
This source file is part of OGRE
|
||||
(Object-oriented Graphics Rendering Engine)
|
||||
For the latest info, see http://www.ogre3d.org
|
||||
|
||||
Copyright (c) 2000-2014 Torus Knot Software Ltd
|
||||
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.
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Program Name: SGXLib_NormalMapLighting
|
||||
// Program Desc: Normal map lighting functions.
|
||||
// Program Type: Vertex/Pixel shader
|
||||
// Language: GLSL
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void SGX_FetchNormal(in sampler2D s,
|
||||
in vec2 uv,
|
||||
out vec3 vOut)
|
||||
{
|
||||
vOut = 2.0 * texture2D(s, uv).xyz - 1.0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void SGX_CalculateTBN(in vec3 vNormal,
|
||||
in vec4 vTangent,
|
||||
out mat3 TBN)
|
||||
{
|
||||
vec3 vBinormal = cross(vNormal, vTangent.xyz) * vTangent.w;
|
||||
|
||||
// direction: from tangent space to world
|
||||
TBN = mtxFromCols(vTangent.xyz, vBinormal, vNormal);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void SGX_Generate_Parallax_Texcoord(in sampler2D normalHeightMap,
|
||||
in vec2 texCoord,
|
||||
in vec3 viewPos,
|
||||
in float heightScale,
|
||||
in mat3 TBN,
|
||||
out vec2 newTexCoord)
|
||||
{
|
||||
//Calculate eye direction
|
||||
vec3 eyeVec = mul(-viewPos, TBN);
|
||||
eyeVec = normalize(eyeVec);
|
||||
#ifndef TERRAIN_PARALLAX_MAPPING
|
||||
eyeVec.y = -eyeVec.y; //Inverse y
|
||||
#endif
|
||||
|
||||
newTexCoord = texCoord;
|
||||
|
||||
#ifndef POM_LAYER_COUNT
|
||||
//Simple parallax mapping
|
||||
float height = 1.0f - texture2D(normalHeightMap, newTexCoord).a;
|
||||
|
||||
#ifndef TERRAIN_PARALLAX_MAPPING
|
||||
vec2 p = eyeVec.xy / eyeVec.z * (height * heightScale);
|
||||
#else
|
||||
vec2 p = eyeVec.xy * (height * heightScale);
|
||||
#endif
|
||||
|
||||
newTexCoord = newTexCoord - p;
|
||||
#else
|
||||
// parallax occlusion mapping
|
||||
#ifdef POM_MAX_DISTANCE
|
||||
if (abs(viewPos.z) > POM_MAX_DISTANCE)
|
||||
return;
|
||||
#endif
|
||||
|
||||
//Configure steep mapping layering.
|
||||
float layerDepth = 1.0 / float(POM_LAYER_COUNT);
|
||||
float currentLayerDepth = 0.0;
|
||||
vec2 parallaxShift = (eyeVec.xy) * heightScale;
|
||||
vec2 deltaTexCoords = parallaxShift / float(POM_LAYER_COUNT);
|
||||
|
||||
float currentDepthMapValue = 1.0f - texture2D(normalHeightMap, newTexCoord).a;
|
||||
|
||||
//Loop through layers and break early if match found.
|
||||
for (int currentLayerId = 0; currentLayerId < POM_LAYER_COUNT; currentLayerId++)
|
||||
{
|
||||
// shift texture coordinates along direction of P
|
||||
newTexCoord -= deltaTexCoords;
|
||||
|
||||
// get depthmap value at current texture coordinates
|
||||
currentDepthMapValue = 1.0f - texture2D(normalHeightMap, newTexCoord).a;
|
||||
|
||||
//Break if layer height matched
|
||||
if (currentLayerDepth > currentDepthMapValue)
|
||||
break;
|
||||
|
||||
// get depth of next layer
|
||||
currentLayerDepth += layerDepth;
|
||||
}
|
||||
|
||||
// get texture coordinates before collision (reverse operations)
|
||||
vec2 prevTexCoords = newTexCoord + deltaTexCoords;
|
||||
|
||||
// get depth after and before collision for linear interpolation
|
||||
float afterDepth = currentDepthMapValue - currentLayerDepth;
|
||||
float beforeDepth = (1.0f - texture2D(normalHeightMap, prevTexCoords).a) - currentLayerDepth + layerDepth;
|
||||
|
||||
// interpolation of texture coordinates
|
||||
float weight = afterDepth / (afterDepth - beforeDepth);
|
||||
newTexCoord = mix(newTexCoord, prevTexCoords, weight);
|
||||
#endif
|
||||
}
|
||||
172
resources/shaderlib/SGXLib_PerPixelLighting.glsl
Normal file
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
-----------------------------------------------------------------------------
|
||||
This source file is part of OGRE
|
||||
(Object-oriented Graphics Rendering Engine)
|
||||
For the latest info, see http://www.ogre3d.org
|
||||
|
||||
Copyright (c) 2000-2014 Torus Knot Software Ltd
|
||||
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.
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Program Name: SGXLib_Lighting
|
||||
// Program Desc: Per pixel lighting functions.
|
||||
// Program Type: Vertex/Pixel shader
|
||||
// Language: GLSL
|
||||
// Notes: Implements core functions for FFPLighting class.
|
||||
// based on lighting engine.
|
||||
// See http://msdn.microsoft.com/en-us/library/bb147178.aspx
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "RTSLib_Lighting.glsl"
|
||||
#ifdef HAVE_AREA_LIGHTS
|
||||
#include "RTSLib_LTC.glsl"
|
||||
#endif
|
||||
|
||||
#ifdef OGRE_HLSL
|
||||
void SGX_Flip_Backface_Normal(in float triArea, in float targetFlipped, inout vec3 normal)
|
||||
{
|
||||
#if OGRE_HLSL == 3
|
||||
triArea *= -1.0;
|
||||
triArea *= targetFlipped;
|
||||
#endif
|
||||
if(triArea < 0.0)
|
||||
normal *= -1.0;
|
||||
}
|
||||
#else
|
||||
void SGX_Flip_Backface_Normal(in bool frontFacing, in float targetFlipped, inout vec3 normal)
|
||||
{
|
||||
if(!frontFacing)
|
||||
normal *= -1.0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void evaluateLight(
|
||||
in vec3 vNormal,
|
||||
in vec3 vViewPos,
|
||||
in vec4 vLightPos,
|
||||
in vec4 vAttParams,
|
||||
in vec4 vLightDirView,
|
||||
in vec4 spotParams,
|
||||
in vec4 vDiffuseColour,
|
||||
inout vec3 vOutDiffuse
|
||||
#if defined(TVC_DIFFUSE) || defined(TVC_SPECULAR)
|
||||
, in vec4 vInVertexColour
|
||||
#endif
|
||||
#ifdef USE_SPECULAR
|
||||
, in vec4 vSpecularColour,
|
||||
in float fSpecularPower,
|
||||
inout vec3 vOutSpecular
|
||||
#endif
|
||||
#ifdef SHADOWLIGHT_COUNT
|
||||
, in float shadowFactor
|
||||
#endif
|
||||
#ifdef HAVE_AREA_LIGHTS
|
||||
, in sampler2D ltcLUT1,
|
||||
in sampler2D ltcLUT2
|
||||
#endif
|
||||
)
|
||||
{
|
||||
|
||||
vec3 vLightView = vLightPos.xyz;
|
||||
float fLightD = 0.0;
|
||||
|
||||
#ifdef TVC_DIFFUSE
|
||||
vDiffuseColour *= vInVertexColour;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_AREA_LIGHTS
|
||||
if(spotParams.w == 2.0)
|
||||
{
|
||||
// rect area light
|
||||
vec3 dcol = vDiffuseColour.rgb;
|
||||
#ifdef USE_SPECULAR
|
||||
#ifdef TVC_SPECULAR
|
||||
vSpecularColour *= vInVertexColour;
|
||||
#endif
|
||||
vec3 scol = vSpecularColour.rgb;
|
||||
#else
|
||||
vec3 scol = vec3_splat(0.0);
|
||||
float fSpecularPower = 0.0;
|
||||
#endif
|
||||
float roughness = saturate(1.0 - fSpecularPower/128.0); // convert specular to roughness
|
||||
roughness *= roughness; // perceptual to physical roughness
|
||||
evaluateRectLight(ltcLUT1, ltcLUT2, roughness, normalize(vNormal), vViewPos, vLightPos.xyz, spotParams.xyz, vAttParams.xyz, scol, dcol);
|
||||
|
||||
#ifdef SHADOWLIGHT_COUNT
|
||||
dcol *= shadowFactor;
|
||||
scol *= shadowFactor;
|
||||
#endif
|
||||
|
||||
// linear to gamma
|
||||
dcol = pow(dcol, vec3_splat(1.0/2.2));
|
||||
vOutDiffuse.rgb = saturate(vOutDiffuse.rgb + dcol);
|
||||
#ifdef USE_SPECULAR
|
||||
scol = pow(scol, vec3_splat(1.0/2.2));
|
||||
vOutSpecular.rgb = saturate(vOutSpecular.rgb + scol);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (vLightPos.w != 0.0)
|
||||
{
|
||||
vLightView -= vViewPos; // to light
|
||||
fLightD = length(vLightView);
|
||||
|
||||
if(fLightD > vAttParams.x)
|
||||
return;
|
||||
}
|
||||
|
||||
vLightView = normalize(vLightView);
|
||||
vec3 vNormalView = normalize(vNormal);
|
||||
float nDotL = saturate(dot(vNormalView, vLightView));
|
||||
|
||||
if (nDotL <= 0.0)
|
||||
return;
|
||||
|
||||
float fAtten = getDistanceAttenuation(vAttParams.yzw, fLightD);
|
||||
|
||||
#ifdef SHADOWLIGHT_COUNT
|
||||
fAtten *= shadowFactor;
|
||||
#endif
|
||||
|
||||
if(spotParams.w != 0.0)
|
||||
{
|
||||
fAtten *= getAngleAttenuation(spotParams.xyz, vLightDirView.xyz, vLightView);
|
||||
}
|
||||
|
||||
vOutDiffuse += vDiffuseColour.rgb * nDotL * fAtten;
|
||||
vOutDiffuse = saturate(vOutDiffuse);
|
||||
|
||||
#ifdef USE_SPECULAR
|
||||
vec3 vView = -normalize(vViewPos);
|
||||
vec3 vHalfWay = normalize(vView + vLightView);
|
||||
float nDotH = saturate(dot(vNormalView, vHalfWay));
|
||||
#ifdef TVC_SPECULAR
|
||||
vSpecularColour *= vInVertexColour;
|
||||
#endif
|
||||
#ifdef NORMALISED
|
||||
vSpecularColour *= (fSpecularPower + 8.0)/(8.0 * M_PI);
|
||||
#endif
|
||||
vOutSpecular += vSpecularColour.rgb * pow(nDotH, fSpecularPower) * fAtten;
|
||||
vOutSpecular = saturate(vOutSpecular);
|
||||
#endif
|
||||
}
|
||||
47
resources/shaderlib/SGXLib_TriplanarTexturing.glsl
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
-----------------------------------------------------------------------------
|
||||
This source file is part of OGRE
|
||||
(Object-oriented Graphics Rendering Engine)
|
||||
For the latest info, see http://www.ogre3d.org
|
||||
|
||||
Copyright (c) 2000-2014 Torus Knot Software Ltd
|
||||
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.
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void SGX_TriplanarTexturing(in vec4 diffuse, in vec3 normal, in vec4 position, in sampler2D texFromX, in sampler2D texFromY, in sampler2D texFromZ, in vec3 parameters, out vec4 cOut)
|
||||
{
|
||||
vec3 blendWeights = abs(normalize(normal));
|
||||
blendWeights = blendWeights - parameters.y;
|
||||
blendWeights = pow(max(blendWeights, vec3(0.0, 0.0, 0.0)), parameters.zzz);
|
||||
float tot = (blendWeights.x + blendWeights.y + blendWeights.z);
|
||||
blendWeights /= vec3(tot, tot, tot);
|
||||
// Move the planar mapping a bit according to the normal length to avoid bad looking skirts.
|
||||
float nLength = length(normal - 1.0);
|
||||
vec2 coord1 = (position.yz + nLength) * parameters.x;
|
||||
vec2 coord2 = (position.zx + nLength) * parameters.x;
|
||||
vec2 coord3 = (position.xy + nLength) * parameters.x;
|
||||
|
||||
vec4 col1 = texture2D(texFromX, coord1);
|
||||
vec4 col2 = texture2D(texFromY, coord2);
|
||||
vec4 col3 = texture2D(texFromZ, coord3);
|
||||
cOut = diffuse * vec4(col1.xyz * blendWeights.x +
|
||||
col2.xyz * blendWeights.y +
|
||||
col3.xyz * blendWeights.z, 1);
|
||||
}
|
||||
19
resources/shaderlib/SGXLib_WBOIT.glsl
Normal file
@@ -0,0 +1,19 @@
|
||||
// This file is part of the OGRE project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at https://www.ogre3d.org/licensing.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
float weight(float z, float a)
|
||||
{
|
||||
// from https://casual-effects.blogspot.com/2015/03/implemented-weighted-blended-order.html
|
||||
return clamp(pow(min(1.0, a * 10.0) + 0.01, 3.0) * 1e8 * pow(1.0 - z * 0.9, 3.0), 1e-2, 3e3);
|
||||
}
|
||||
|
||||
void SGX_WBOIT(float depth, inout vec4 accum, out vec4 revealage)
|
||||
{
|
||||
vec4 colour = accum;
|
||||
// Weighted Blended Order-Independent Transparency, Listing 4
|
||||
float w = weight(depth, colour.a);
|
||||
accum = vec4(colour.rgb * w * colour.a, colour.a);
|
||||
revealage = vec4_splat(colour.a * w);
|
||||
}
|
||||
BIN
resources/shaderlib/dfgLUTmultiscatter.dds
Normal file
BIN
resources/shaderlib/ltc_1.dds
Normal file
BIN
resources/shaderlib/ltc_2.dds
Normal file
BIN
resources/terrain/Bricks076C_diffspec.dds
Normal file
BIN
resources/terrain/Bricks076C_normheight.dds
Normal file
BIN
resources/terrain/Ground23_col.jpg
Normal file
|
After Width: | Height: | Size: 506 KiB |
BIN
resources/terrain/Ground23_normheight.dds
Normal file
BIN
resources/terrain/Ground23_spec.png
Normal file
|
After Width: | Height: | Size: 676 KiB |
BIN
resources/terrain/Ground37_diffspec.dds
Normal file
BIN
resources/terrain/Ground37_normheight.dds
Normal file
1
resources/terrain/README.md
Normal file
@@ -0,0 +1 @@
|
||||
Textures are CC0 from https://cc0textures.com/ adapted for Ogre
|
||||
BIN
resources/terrain/Rock20_diffspec.dds
Normal file
BIN
resources/terrain/Rock20_normheight.dds
Normal file
83
resources/terrain/TerrainSurface.glsl
Normal file
@@ -0,0 +1,83 @@
|
||||
void transformToTS(in vec3 TSnormal, in mat3 normalMatrix, inout vec3 normal)
|
||||
{
|
||||
// derive the tangent space basis
|
||||
// we do this in the pixel shader because we don't have per-vertex normals
|
||||
// because of the LOD, we use a normal map
|
||||
// tangent is always +x or -z in object space depending on alignment
|
||||
#ifdef TERRAIN_ALIGN_Y_Z
|
||||
vec3 tangent = vec3(0, 0, -1);
|
||||
#else
|
||||
vec3 tangent = vec3(1, 0, 0);
|
||||
#endif
|
||||
normal = normalize(normal);
|
||||
tangent = normalize(mul(normalMatrix, tangent));
|
||||
vec3 binormal = cross(tangent, normal);
|
||||
// note, now we need to re-cross to derive tangent again because it wasn't orthonormal
|
||||
tangent = cross(normal, binormal);
|
||||
// derive final matrix
|
||||
mat3 TBN = mtxFromCols(tangent, binormal, normal);
|
||||
|
||||
normal = mul(TBN, TSnormal);
|
||||
}
|
||||
|
||||
void getShadowFactor(in sampler2D lightmap, in vec2 uv, inout float shadowFactor)
|
||||
{
|
||||
float lmShadow = texture2D(lightmap, uv).x;
|
||||
shadowFactor = min(shadowFactor, lmShadow);
|
||||
}
|
||||
|
||||
#define MIN_BLEND_WEIGHT 0.0039 // 1/255
|
||||
|
||||
void blendTerrainLayer(in float blendWeight, in f32vec2 uv0, in float uvMul,
|
||||
#ifdef TERRAIN_PARALLAX_MAPPING
|
||||
in vec3 viewPos, in float scaleBias, in mat3 TBN,
|
||||
#endif
|
||||
#ifdef TERRAIN_NORMAL_MAPPING
|
||||
in sampler2D normtex, inout vec3 normal,
|
||||
#endif
|
||||
in sampler2D difftex, inout vec4 diffuseSpec)
|
||||
{
|
||||
if(blendWeight < MIN_BLEND_WEIGHT)
|
||||
return;
|
||||
|
||||
// generate UV
|
||||
vec2 uv = mod(uv0 * uvMul, 1.0);
|
||||
|
||||
#ifdef TERRAIN_PARALLAX_MAPPING
|
||||
SGX_Generate_Parallax_Texcoord(normtex, uv, viewPos, scaleBias, TBN, uv);
|
||||
#endif
|
||||
|
||||
// sample diffuse texture
|
||||
vec4 diffuseSpecTex = texture2D(difftex, uv);
|
||||
// apply to common
|
||||
diffuseSpec = mix(diffuseSpec, diffuseSpecTex, blendWeight);
|
||||
|
||||
#ifdef TERRAIN_NORMAL_MAPPING
|
||||
vec3 TSnormal;
|
||||
// access TS normal map
|
||||
SGX_FetchNormal(normtex, uv, TSnormal);
|
||||
// Partial Derivative Blending https://blog.selfshadow.com/publications/blending-in-detail/
|
||||
normal = normalize(vec3(mix(normal.xy*TSnormal.z, TSnormal.xy*normal.z, blendWeight), TSnormal.z*normal.z));
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void SGX_CalculateTerrainTBN(in vec3 normal, in mat3 normalMatrix, out mat3 TBN)
|
||||
{
|
||||
// derive the tangent space basis
|
||||
// we do this in the pixel shader because we don't have per-vertex normals
|
||||
// because of the LOD, we use a normal map
|
||||
// tangent is always +x or -z in object space depending on alignment
|
||||
#ifdef TERRAIN_ALIGN_Y_Z
|
||||
vec3 tangent = vec3(0, 0, -1);
|
||||
#else
|
||||
vec3 tangent = vec3(1, 0, 0);
|
||||
#endif
|
||||
normal = normalize(normal);
|
||||
tangent = normalize(mul(normalMatrix, tangent));
|
||||
vec3 binormal = cross(tangent, normal);
|
||||
// note, now we need to re-cross to derive tangent again because it wasn't orthonormal
|
||||
tangent = cross(normal, binormal);
|
||||
// derive final matrix
|
||||
TBN = mtxFromCols(tangent, binormal, normal);
|
||||
}
|
||||
36
resources/terrain/TerrainTransforms.glsl
Normal file
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* @param delta: lodDelta, lodThreshold (vertex attribute)
|
||||
* @param lodMorph: morph amount, morph targetLOD (uniform)
|
||||
*/
|
||||
void applyLODMorph(vec2 delta, vec2 lodMorph, inout float height
|
||||
#ifdef TERRAIN_DEBUG
|
||||
, out vec2 lodInfo
|
||||
#endif
|
||||
)
|
||||
{
|
||||
// determine whether to apply the LOD morph to this vertex
|
||||
// we store the deltas against all vertices so we only want to apply
|
||||
// the morph to the ones which would disappear.
|
||||
// If we subtract
|
||||
// the lodThreshold from the targetLOD, and arrange to only morph if the
|
||||
// result is negative (it will only be -1 in fact, since after that
|
||||
// the vertex will never be indexed), we will achieve our aim.
|
||||
// sign(lodThreshold - targetLOD) == -1 is to morph
|
||||
|
||||
// this will either be 1 (morph) or 0 (don't morph)
|
||||
float toMorph = -min(0.0, sign(delta.y - lodMorph.y));
|
||||
height += delta.x * toMorph * lodMorph.x;
|
||||
|
||||
#ifdef TERRAIN_DEBUG
|
||||
// LOD level (-1 since value is target level, we want to display actual)
|
||||
lodInfo.x = (lodMorph.y - 1) / NUM_LODS;
|
||||
// LOD morph
|
||||
lodInfo.y = toMorph * lodMorph.x;
|
||||
#endif
|
||||
}
|
||||
|
||||
void expandVertex(mat4 idxToObjectSpace, float baseUVScale, vec2 idx, float height, out vec4 position, out vec2 uv)
|
||||
{
|
||||
position = mul(idxToObjectSpace, vec4(idx, height, 1));
|
||||
uv = vec2(idx.x * baseUVScale, 1.0 - idx.y * baseUVScale);
|
||||
}
|
||||
BIN
resources/terrain/terr_dirt-grass.jpg
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
resources/terrain/terr_rock-dirt.jpg
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
resources/terrain/terr_rock6.jpg
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
resources/terrain/terrain.png
Normal file
|
After Width: | Height: | Size: 101 KiB |
BIN
resources/terrain/terrain_detail.jpg
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
resources/terrain/terrain_texture.jpg
Normal file
|
After Width: | Height: | Size: 70 KiB |
BIN
skybox/early_morning_bk.jpg
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
skybox/early_morning_dn.jpg
Normal file
|
After Width: | Height: | Size: 6.7 KiB |
BIN
skybox/early_morning_fr.jpg
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
skybox/early_morning_lf.jpg
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
skybox/early_morning_rt.jpg
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
skybox/early_morning_up.jpg
Normal file
|
After Width: | Height: | Size: 14 KiB |
37
skybox/skybox.material
Normal file
@@ -0,0 +1,37 @@
|
||||
material Skybox
|
||||
{
|
||||
technique
|
||||
{
|
||||
pass
|
||||
{
|
||||
lighting off
|
||||
depth_write off
|
||||
|
||||
texture_unit
|
||||
{
|
||||
texture early_morning.jpg cubic
|
||||
tex_address_mode clamp
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
material Skybox/Dynamic
|
||||
{
|
||||
technique
|
||||
{
|
||||
pass
|
||||
{
|
||||
lighting off
|
||||
depth_write off
|
||||
ambient 1.0 1.0 1.0 1.0
|
||||
diffuse 0.0 0.0 1.0 1.0
|
||||
specular 0.0 0.0 0.0 1.0
|
||||
vertex_program_ref debug_vp
|
||||
{
|
||||
}
|
||||
fragment_program_ref debug_fp
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
30
src/lua/CMakeLists.txt
Normal file
@@ -0,0 +1,30 @@
|
||||
#file(GLOB LUA_SRC lua-5.4.8/src/*.c)
|
||||
|
||||
set(LUA_OBJ
|
||||
# core
|
||||
lapi.o lcode.o lctype.o ldebug.o ldo.o ldump.o
|
||||
lfunc.o lgc.o llex.o lmem.o lobject.o lopcodes.o
|
||||
lparser.o lstate.o lstring.o ltable.o ltm.o
|
||||
lundump.o lvm.o lzio.o
|
||||
lauxlib.o lbaselib.o lcorolib.o ldblib.o liolib.o
|
||||
lmathlib.o loadlib.o loslib.o lstrlib.o ltablib.o
|
||||
lutf8lib.o linit.o
|
||||
#lib
|
||||
lauxlib.o lbaselib.o lcorolib.o ldblib.o liolib.o
|
||||
lmathlib.o loadlib.o loslib.o lstrlib.o ltablib.o
|
||||
lutf8lib.o linit.o)
|
||||
set(LUA_SRC)
|
||||
foreach(LUA_FILE ${LUA_OBJ})
|
||||
string(REPLACE ".o" ".c" LUA_SRC_ITEM ${LUA_FILE})
|
||||
list(APPEND LUA_SRC lua-5.4.8/src/${LUA_SRC_ITEM})
|
||||
endforeach()
|
||||
add_library(lua ${LUA_SRC})
|
||||
target_include_directories(lua PRIVATE lua-5.4.8/src)
|
||||
add_executable(luavm lua-5.4.8/src/lua.c)
|
||||
target_link_libraries(luavm lua m)
|
||||
target_include_directories(luavm PRIVATE lua-5.4.8/src)
|
||||
add_executable(luac lua-5.4.8/src/luac.c)
|
||||
target_link_libraries(luac lua m)
|
||||
target_include_directories(luac PRIVATE lua-5.4.8/src)
|
||||
|
||||
|
||||
106
src/lua/lua-5.4.8/Makefile
Normal file
@@ -0,0 +1,106 @@
|
||||
# Makefile for installing Lua
|
||||
# See doc/readme.html for installation and customization instructions.
|
||||
|
||||
# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT =======================
|
||||
|
||||
# Your platform. See PLATS for possible values.
|
||||
PLAT= guess
|
||||
|
||||
# Where to install. The installation starts in the src and doc directories,
|
||||
# so take care if INSTALL_TOP is not an absolute path. See the local target.
|
||||
# You may want to make INSTALL_LMOD and INSTALL_CMOD consistent with
|
||||
# LUA_ROOT, LUA_LDIR, and LUA_CDIR in luaconf.h.
|
||||
INSTALL_TOP= /usr/local
|
||||
INSTALL_BIN= $(INSTALL_TOP)/bin
|
||||
INSTALL_INC= $(INSTALL_TOP)/include
|
||||
INSTALL_LIB= $(INSTALL_TOP)/lib
|
||||
INSTALL_MAN= $(INSTALL_TOP)/man/man1
|
||||
INSTALL_LMOD= $(INSTALL_TOP)/share/lua/$V
|
||||
INSTALL_CMOD= $(INSTALL_TOP)/lib/lua/$V
|
||||
|
||||
# How to install. If your install program does not support "-p", then
|
||||
# you may have to run ranlib on the installed liblua.a.
|
||||
INSTALL= install -p
|
||||
INSTALL_EXEC= $(INSTALL) -m 0755
|
||||
INSTALL_DATA= $(INSTALL) -m 0644
|
||||
#
|
||||
# If you don't have "install" you can use "cp" instead.
|
||||
# INSTALL= cp -p
|
||||
# INSTALL_EXEC= $(INSTALL)
|
||||
# INSTALL_DATA= $(INSTALL)
|
||||
|
||||
# Other utilities.
|
||||
MKDIR= mkdir -p
|
||||
RM= rm -f
|
||||
|
||||
# == END OF USER SETTINGS -- NO NEED TO CHANGE ANYTHING BELOW THIS LINE =======
|
||||
|
||||
# Convenience platforms targets.
|
||||
PLATS= guess aix bsd c89 freebsd generic ios linux linux-readline macosx mingw posix solaris
|
||||
|
||||
# What to install.
|
||||
TO_BIN= lua luac
|
||||
TO_INC= lua.h luaconf.h lualib.h lauxlib.h lua.hpp
|
||||
TO_LIB= liblua.a
|
||||
TO_MAN= lua.1 luac.1
|
||||
|
||||
# Lua version and release.
|
||||
V= 5.4
|
||||
R= $V.8
|
||||
|
||||
# Targets start here.
|
||||
all: $(PLAT)
|
||||
|
||||
$(PLATS) help test clean:
|
||||
@cd src && $(MAKE) $@
|
||||
|
||||
install: dummy
|
||||
cd src && $(MKDIR) $(INSTALL_BIN) $(INSTALL_INC) $(INSTALL_LIB) $(INSTALL_MAN) $(INSTALL_LMOD) $(INSTALL_CMOD)
|
||||
cd src && $(INSTALL_EXEC) $(TO_BIN) $(INSTALL_BIN)
|
||||
cd src && $(INSTALL_DATA) $(TO_INC) $(INSTALL_INC)
|
||||
cd src && $(INSTALL_DATA) $(TO_LIB) $(INSTALL_LIB)
|
||||
cd doc && $(INSTALL_DATA) $(TO_MAN) $(INSTALL_MAN)
|
||||
|
||||
uninstall:
|
||||
cd src && cd $(INSTALL_BIN) && $(RM) $(TO_BIN)
|
||||
cd src && cd $(INSTALL_INC) && $(RM) $(TO_INC)
|
||||
cd src && cd $(INSTALL_LIB) && $(RM) $(TO_LIB)
|
||||
cd doc && cd $(INSTALL_MAN) && $(RM) $(TO_MAN)
|
||||
|
||||
local:
|
||||
$(MAKE) install INSTALL_TOP=../install
|
||||
|
||||
# make may get confused with install/ if it does not support .PHONY.
|
||||
dummy:
|
||||
|
||||
# Echo config parameters.
|
||||
echo:
|
||||
@cd src && $(MAKE) -s echo
|
||||
@echo "PLAT= $(PLAT)"
|
||||
@echo "V= $V"
|
||||
@echo "R= $R"
|
||||
@echo "TO_BIN= $(TO_BIN)"
|
||||
@echo "TO_INC= $(TO_INC)"
|
||||
@echo "TO_LIB= $(TO_LIB)"
|
||||
@echo "TO_MAN= $(TO_MAN)"
|
||||
@echo "INSTALL_TOP= $(INSTALL_TOP)"
|
||||
@echo "INSTALL_BIN= $(INSTALL_BIN)"
|
||||
@echo "INSTALL_INC= $(INSTALL_INC)"
|
||||
@echo "INSTALL_LIB= $(INSTALL_LIB)"
|
||||
@echo "INSTALL_MAN= $(INSTALL_MAN)"
|
||||
@echo "INSTALL_LMOD= $(INSTALL_LMOD)"
|
||||
@echo "INSTALL_CMOD= $(INSTALL_CMOD)"
|
||||
@echo "INSTALL_EXEC= $(INSTALL_EXEC)"
|
||||
@echo "INSTALL_DATA= $(INSTALL_DATA)"
|
||||
|
||||
# Echo pkg-config data.
|
||||
pc:
|
||||
@echo "version=$R"
|
||||
@echo "prefix=$(INSTALL_TOP)"
|
||||
@echo "libdir=$(INSTALL_LIB)"
|
||||
@echo "includedir=$(INSTALL_INC)"
|
||||
|
||||
# Targets that do not create files (not all makes understand .PHONY).
|
||||
.PHONY: all $(PLATS) help test clean install uninstall local dummy echo pc
|
||||
|
||||
# (end of Makefile)
|
||||
6
src/lua/lua-5.4.8/README
Normal file
@@ -0,0 +1,6 @@
|
||||
|
||||
This is Lua 5.4.8, released on 21 May 2025.
|
||||
|
||||
For installation instructions, license details, and
|
||||
further information about Lua, see doc/readme.html.
|
||||
|
||||
BIN
src/lua/lua-5.4.8/doc/OSIApproved_100X125.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
678
src/lua/lua-5.4.8/doc/contents.html
Normal file
@@ -0,0 +1,678 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>Lua 5.4 Reference Manual - contents</TITLE>
|
||||
<LINK REL="stylesheet" TYPE="text/css" HREF="lua.css">
|
||||
<LINK REL="stylesheet" TYPE="text/css" HREF="index.css">
|
||||
<META HTTP-EQUIV="content-type" CONTENT="text/html; charset=iso-8859-1">
|
||||
</HEAD>
|
||||
|
||||
<BODY>
|
||||
|
||||
<H1>
|
||||
<A HREF="https://www.lua.org/"><IMG SRC="logo.gif" ALT="Lua"></A>
|
||||
Lua 5.4 Reference Manual
|
||||
</H1>
|
||||
|
||||
<P>
|
||||
The reference manual is the official definition of the Lua language.
|
||||
<BR>
|
||||
For a complete introduction to Lua programming, see the book
|
||||
<A HREF="https://www.lua.org/pil/">Programming in Lua</A>.
|
||||
|
||||
<DIV CLASS="menubar">
|
||||
<A HREF="manual.html">start</A>
|
||||
·
|
||||
<A HREF="#contents">contents</A>
|
||||
·
|
||||
<A HREF="#index">index</A>
|
||||
·
|
||||
<A HREF="https://www.lua.org/manual/">other versions</A>
|
||||
</DIV>
|
||||
|
||||
<P>
|
||||
<SMALL>
|
||||
Copyright © 2020–2025 Lua.org, PUC-Rio.
|
||||
Freely available under the terms of the
|
||||
<A HREF="https://www.lua.org/license.html">Lua license</A>.
|
||||
</SMALL>
|
||||
|
||||
<H2><A NAME="contents">Contents</A></H2>
|
||||
<UL CLASS="contents menubar">
|
||||
<LI><A HREF="manual.html">1 – Introduction</A>
|
||||
<P>
|
||||
<LI><A HREF="manual.html#2">2 – Basic Concepts</A>
|
||||
<UL>
|
||||
<LI><A HREF="manual.html#2.1">2.1 – Values and Types</A>
|
||||
<LI><A HREF="manual.html#2.2">2.2 – Environments and the Global Environment</A>
|
||||
<LI><A HREF="manual.html#2.3">2.3 – Error Handling</A>
|
||||
<LI><A HREF="manual.html#2.4">2.4 – Metatables and Metamethods</A>
|
||||
<LI><A HREF="manual.html#2.5">2.5 – Garbage Collection</A>
|
||||
<UL>
|
||||
<LI><A HREF="manual.html#2.5.1">2.5.1 – Incremental Garbage Collection</A>
|
||||
<LI><A HREF="manual.html#2.5.2">2.5.2 – Generational Garbage Collection</A>
|
||||
<LI><A HREF="manual.html#2.5.3">2.5.3 – Garbage-Collection Metamethods</A>
|
||||
<LI><A HREF="manual.html#2.5.4">2.5.4 – Weak Tables</A>
|
||||
</UL>
|
||||
<LI><A HREF="manual.html#2.6">2.6 – Coroutines</A>
|
||||
</UL>
|
||||
<P>
|
||||
<LI><A HREF="manual.html#3">3 – The Language</A>
|
||||
<UL>
|
||||
<LI><A HREF="manual.html#3.1">3.1 – Lexical Conventions</A>
|
||||
<LI><A HREF="manual.html#3.2">3.2 – Variables</A>
|
||||
<LI><A HREF="manual.html#3.3">3.3 – Statements</A>
|
||||
<UL>
|
||||
<LI><A HREF="manual.html#3.3.1">3.3.1 – Blocks</A>
|
||||
<LI><A HREF="manual.html#3.3.2">3.3.2 – Chunks</A>
|
||||
<LI><A HREF="manual.html#3.3.3">3.3.3 – Assignment</A>
|
||||
<LI><A HREF="manual.html#3.3.4">3.3.4 – Control Structures</A>
|
||||
<LI><A HREF="manual.html#3.3.5">3.3.5 – For Statement</A>
|
||||
<LI><A HREF="manual.html#3.3.6">3.3.6 – Function Calls as Statements</A>
|
||||
<LI><A HREF="manual.html#3.3.7">3.3.7 – Local Declarations</A>
|
||||
<LI><A HREF="manual.html#3.3.8">3.3.8 – To-be-closed Variables</A>
|
||||
</UL>
|
||||
<LI><A HREF="manual.html#3.4">3.4 – Expressions</A>
|
||||
<UL>
|
||||
<LI><A HREF="manual.html#3.4.1">3.4.1 – Arithmetic Operators</A>
|
||||
<LI><A HREF="manual.html#3.4.2">3.4.2 – Bitwise Operators</A>
|
||||
<LI><A HREF="manual.html#3.4.3">3.4.3 – Coercions and Conversions</A>
|
||||
<LI><A HREF="manual.html#3.4.4">3.4.4 – Relational Operators</A>
|
||||
<LI><A HREF="manual.html#3.4.5">3.4.5 – Logical Operators</A>
|
||||
<LI><A HREF="manual.html#3.4.6">3.4.6 – Concatenation</A>
|
||||
<LI><A HREF="manual.html#3.4.7">3.4.7 – The Length Operator</A>
|
||||
<LI><A HREF="manual.html#3.4.8">3.4.8 – Precedence</A>
|
||||
<LI><A HREF="manual.html#3.4.9">3.4.9 – Table Constructors</A>
|
||||
<LI><A HREF="manual.html#3.4.10">3.4.10 – Function Calls</A>
|
||||
<LI><A HREF="manual.html#3.4.11">3.4.11 – Function Definitions</A>
|
||||
<LI><A HREF="manual.html#3.4.12">3.4.12 – Lists of expressions, multiple results, and adjustment<A>
|
||||
|
||||
</UL>
|
||||
<LI><A HREF="manual.html#3.5">3.5 – Visibility Rules</A>
|
||||
</UL>
|
||||
<P>
|
||||
<LI><A HREF="manual.html#4">4 – The Application Program Interface</A>
|
||||
<UL>
|
||||
<LI><A HREF="manual.html#4.1">4.1 – The Stack</A>
|
||||
<UL>
|
||||
<LI><A HREF="manual.html#4.1.1">4.1.1 – Stack Size</A>
|
||||
<LI><A HREF="manual.html#4.1.2">4.1.2 – Valid and Acceptable Indices</A>
|
||||
<LI><A HREF="manual.html#4.1.3">4.1.3 – Pointers to strings</A>
|
||||
</UL>
|
||||
<LI><A HREF="manual.html#4.2">4.2 – C Closures</A>
|
||||
<LI><A HREF="manual.html#4.3">4.3 – Registry</A>
|
||||
<LI><A HREF="manual.html#4.4">4.4 – Error Handling in C</A>
|
||||
<UL>
|
||||
<LI><A HREF="manual.html#4.4.1">4.4.1 – Status Codes</A>
|
||||
</UL>
|
||||
<LI><A HREF="manual.html#4.5">4.5 – Handling Yields in C</A>
|
||||
<LI><A HREF="manual.html#4.6">4.6 – Functions and Types</A>
|
||||
<LI><A HREF="manual.html#4.7">4.7 – The Debug Interface</A>
|
||||
</UL>
|
||||
<P>
|
||||
<LI><A HREF="manual.html#5">5 – The Auxiliary Library</A>
|
||||
<UL>
|
||||
<LI><A HREF="manual.html#5.1">5.1 – Functions and Types</A>
|
||||
</UL>
|
||||
<P>
|
||||
<LI><A HREF="manual.html#6">6 – The Standard Libraries</A>
|
||||
<UL>
|
||||
<LI><A HREF="manual.html#6.1">6.1 – Basic Functions</A>
|
||||
<LI><A HREF="manual.html#6.2">6.2 – Coroutine Manipulation</A>
|
||||
<LI><A HREF="manual.html#6.3">6.3 – Modules</A>
|
||||
<LI><A HREF="manual.html#6.4">6.4 – String Manipulation</A>
|
||||
<UL>
|
||||
<LI><A HREF="manual.html#6.4.1">6.4.1 – Patterns</A>
|
||||
<LI><A HREF="manual.html#6.4.2">6.4.2 – Format Strings for Pack and Unpack</A>
|
||||
</UL>
|
||||
<LI><A HREF="manual.html#6.5">6.5 – UTF-8 Support</A>
|
||||
<LI><A HREF="manual.html#6.6">6.6 – Table Manipulation</A>
|
||||
<LI><A HREF="manual.html#6.7">6.7 – Mathematical Functions</A>
|
||||
<LI><A HREF="manual.html#6.8">6.8 – Input and Output Facilities</A>
|
||||
<LI><A HREF="manual.html#6.9">6.9 – Operating System Facilities</A>
|
||||
<LI><A HREF="manual.html#6.10">6.10 – The Debug Library</A>
|
||||
</UL>
|
||||
<P>
|
||||
<LI><A HREF="manual.html#7">7 – Lua Standalone</A>
|
||||
<P>
|
||||
<LI><A HREF="manual.html#8">8 – Incompatibilities with the Previous Version</A>
|
||||
<UL>
|
||||
<LI><A HREF="manual.html#8.1">8.1 – Incompatibilities in the Language</A>
|
||||
<LI><A HREF="manual.html#8.2">8.2 – Incompatibilities in the Libraries</A>
|
||||
<LI><A HREF="manual.html#8.3">8.3 – Incompatibilities in the API</A>
|
||||
</UL>
|
||||
<P>
|
||||
<LI><A HREF="manual.html#9">9 – The Complete Syntax of Lua</A>
|
||||
</UL>
|
||||
|
||||
<H2><A NAME="index">Index</A></H2>
|
||||
<TABLE CLASS="menubar" WIDTH="100%">
|
||||
<TR>
|
||||
<TD>
|
||||
<H3><A NAME="functions">Lua functions</A></H3>
|
||||
<P>
|
||||
<A HREF="manual.html#6.1">basic</A><BR>
|
||||
<A HREF="manual.html#pdf-_G">_G</A><BR>
|
||||
<A HREF="manual.html#pdf-_VERSION">_VERSION</A><BR>
|
||||
<A HREF="manual.html#pdf-assert">assert</A><BR>
|
||||
<A HREF="manual.html#pdf-collectgarbage">collectgarbage</A><BR>
|
||||
<A HREF="manual.html#pdf-dofile">dofile</A><BR>
|
||||
<A HREF="manual.html#pdf-error">error</A><BR>
|
||||
<A HREF="manual.html#pdf-getmetatable">getmetatable</A><BR>
|
||||
<A HREF="manual.html#pdf-ipairs">ipairs</A><BR>
|
||||
<A HREF="manual.html#pdf-load">load</A><BR>
|
||||
<A HREF="manual.html#pdf-loadfile">loadfile</A><BR>
|
||||
<A HREF="manual.html#pdf-next">next</A><BR>
|
||||
<A HREF="manual.html#pdf-pairs">pairs</A><BR>
|
||||
<A HREF="manual.html#pdf-pcall">pcall</A><BR>
|
||||
<A HREF="manual.html#pdf-print">print</A><BR>
|
||||
<A HREF="manual.html#pdf-rawequal">rawequal</A><BR>
|
||||
<A HREF="manual.html#pdf-rawget">rawget</A><BR>
|
||||
<A HREF="manual.html#pdf-rawlen">rawlen</A><BR>
|
||||
<A HREF="manual.html#pdf-rawset">rawset</A><BR>
|
||||
<A HREF="manual.html#pdf-require">require</A><BR>
|
||||
<A HREF="manual.html#pdf-select">select</A><BR>
|
||||
<A HREF="manual.html#pdf-setmetatable">setmetatable</A><BR>
|
||||
<A HREF="manual.html#pdf-tonumber">tonumber</A><BR>
|
||||
<A HREF="manual.html#pdf-tostring">tostring</A><BR>
|
||||
<A HREF="manual.html#pdf-type">type</A><BR>
|
||||
<A HREF="manual.html#pdf-warn">warn</A><BR>
|
||||
<A HREF="manual.html#pdf-xpcall">xpcall</A><BR>
|
||||
|
||||
<P>
|
||||
<A HREF="manual.html#6.2">coroutine</A><BR>
|
||||
<A HREF="manual.html#pdf-coroutine.close">coroutine.close</A><BR>
|
||||
<A HREF="manual.html#pdf-coroutine.create">coroutine.create</A><BR>
|
||||
<A HREF="manual.html#pdf-coroutine.isyieldable">coroutine.isyieldable</A><BR>
|
||||
<A HREF="manual.html#pdf-coroutine.resume">coroutine.resume</A><BR>
|
||||
<A HREF="manual.html#pdf-coroutine.running">coroutine.running</A><BR>
|
||||
<A HREF="manual.html#pdf-coroutine.status">coroutine.status</A><BR>
|
||||
<A HREF="manual.html#pdf-coroutine.wrap">coroutine.wrap</A><BR>
|
||||
<A HREF="manual.html#pdf-coroutine.yield">coroutine.yield</A><BR>
|
||||
|
||||
<P>
|
||||
<A HREF="manual.html#6.10">debug</A><BR>
|
||||
<A HREF="manual.html#pdf-debug.debug">debug.debug</A><BR>
|
||||
<A HREF="manual.html#pdf-debug.gethook">debug.gethook</A><BR>
|
||||
<A HREF="manual.html#pdf-debug.getinfo">debug.getinfo</A><BR>
|
||||
<A HREF="manual.html#pdf-debug.getlocal">debug.getlocal</A><BR>
|
||||
<A HREF="manual.html#pdf-debug.getmetatable">debug.getmetatable</A><BR>
|
||||
<A HREF="manual.html#pdf-debug.getregistry">debug.getregistry</A><BR>
|
||||
<A HREF="manual.html#pdf-debug.getupvalue">debug.getupvalue</A><BR>
|
||||
<A HREF="manual.html#pdf-debug.getuservalue">debug.getuservalue</A><BR>
|
||||
<A HREF="manual.html#pdf-debug.sethook">debug.sethook</A><BR>
|
||||
<A HREF="manual.html#pdf-debug.setlocal">debug.setlocal</A><BR>
|
||||
<A HREF="manual.html#pdf-debug.setmetatable">debug.setmetatable</A><BR>
|
||||
<A HREF="manual.html#pdf-debug.setupvalue">debug.setupvalue</A><BR>
|
||||
<A HREF="manual.html#pdf-debug.setuservalue">debug.setuservalue</A><BR>
|
||||
<A HREF="manual.html#pdf-debug.traceback">debug.traceback</A><BR>
|
||||
<A HREF="manual.html#pdf-debug.upvalueid">debug.upvalueid</A><BR>
|
||||
<A HREF="manual.html#pdf-debug.upvaluejoin">debug.upvaluejoin</A><BR>
|
||||
|
||||
<P>
|
||||
<A HREF="manual.html#6.8">io</A><BR>
|
||||
<A HREF="manual.html#pdf-io.close">io.close</A><BR>
|
||||
<A HREF="manual.html#pdf-io.flush">io.flush</A><BR>
|
||||
<A HREF="manual.html#pdf-io.input">io.input</A><BR>
|
||||
<A HREF="manual.html#pdf-io.lines">io.lines</A><BR>
|
||||
<A HREF="manual.html#pdf-io.open">io.open</A><BR>
|
||||
<A HREF="manual.html#pdf-io.output">io.output</A><BR>
|
||||
<A HREF="manual.html#pdf-io.popen">io.popen</A><BR>
|
||||
<A HREF="manual.html#pdf-io.read">io.read</A><BR>
|
||||
<A HREF="manual.html#pdf-io.stderr">io.stderr</A><BR>
|
||||
<A HREF="manual.html#pdf-io.stdin">io.stdin</A><BR>
|
||||
<A HREF="manual.html#pdf-io.stdout">io.stdout</A><BR>
|
||||
<A HREF="manual.html#pdf-io.tmpfile">io.tmpfile</A><BR>
|
||||
<A HREF="manual.html#pdf-io.type">io.type</A><BR>
|
||||
<A HREF="manual.html#pdf-io.write">io.write</A><BR>
|
||||
|
||||
<A HREF="manual.html#pdf-file:close">file:close</A><BR>
|
||||
<A HREF="manual.html#pdf-file:flush">file:flush</A><BR>
|
||||
<A HREF="manual.html#pdf-file:lines">file:lines</A><BR>
|
||||
<A HREF="manual.html#pdf-file:read">file:read</A><BR>
|
||||
<A HREF="manual.html#pdf-file:seek">file:seek</A><BR>
|
||||
<A HREF="manual.html#pdf-file:setvbuf">file:setvbuf</A><BR>
|
||||
<A HREF="manual.html#pdf-file:write">file:write</A><BR>
|
||||
|
||||
</TD>
|
||||
<TD>
|
||||
<H3> </H3>
|
||||
<P>
|
||||
<A HREF="manual.html#6.7">math</A><BR>
|
||||
<A HREF="manual.html#pdf-math.abs">math.abs</A><BR>
|
||||
<A HREF="manual.html#pdf-math.acos">math.acos</A><BR>
|
||||
<A HREF="manual.html#pdf-math.asin">math.asin</A><BR>
|
||||
<A HREF="manual.html#pdf-math.atan">math.atan</A><BR>
|
||||
<A HREF="manual.html#pdf-math.ceil">math.ceil</A><BR>
|
||||
<A HREF="manual.html#pdf-math.cos">math.cos</A><BR>
|
||||
<A HREF="manual.html#pdf-math.deg">math.deg</A><BR>
|
||||
<A HREF="manual.html#pdf-math.exp">math.exp</A><BR>
|
||||
<A HREF="manual.html#pdf-math.floor">math.floor</A><BR>
|
||||
<A HREF="manual.html#pdf-math.fmod">math.fmod</A><BR>
|
||||
<A HREF="manual.html#pdf-math.huge">math.huge</A><BR>
|
||||
<A HREF="manual.html#pdf-math.log">math.log</A><BR>
|
||||
<A HREF="manual.html#pdf-math.max">math.max</A><BR>
|
||||
<A HREF="manual.html#pdf-math.maxinteger">math.maxinteger</A><BR>
|
||||
<A HREF="manual.html#pdf-math.min">math.min</A><BR>
|
||||
<A HREF="manual.html#pdf-math.mininteger">math.mininteger</A><BR>
|
||||
<A HREF="manual.html#pdf-math.modf">math.modf</A><BR>
|
||||
<A HREF="manual.html#pdf-math.pi">math.pi</A><BR>
|
||||
<A HREF="manual.html#pdf-math.rad">math.rad</A><BR>
|
||||
<A HREF="manual.html#pdf-math.random">math.random</A><BR>
|
||||
<A HREF="manual.html#pdf-math.randomseed">math.randomseed</A><BR>
|
||||
<A HREF="manual.html#pdf-math.sin">math.sin</A><BR>
|
||||
<A HREF="manual.html#pdf-math.sqrt">math.sqrt</A><BR>
|
||||
<A HREF="manual.html#pdf-math.tan">math.tan</A><BR>
|
||||
<A HREF="manual.html#pdf-math.tointeger">math.tointeger</A><BR>
|
||||
<A HREF="manual.html#pdf-math.type">math.type</A><BR>
|
||||
<A HREF="manual.html#pdf-math.ult">math.ult</A><BR>
|
||||
|
||||
<P>
|
||||
<A HREF="manual.html#6.9">os</A><BR>
|
||||
<A HREF="manual.html#pdf-os.clock">os.clock</A><BR>
|
||||
<A HREF="manual.html#pdf-os.date">os.date</A><BR>
|
||||
<A HREF="manual.html#pdf-os.difftime">os.difftime</A><BR>
|
||||
<A HREF="manual.html#pdf-os.execute">os.execute</A><BR>
|
||||
<A HREF="manual.html#pdf-os.exit">os.exit</A><BR>
|
||||
<A HREF="manual.html#pdf-os.getenv">os.getenv</A><BR>
|
||||
<A HREF="manual.html#pdf-os.remove">os.remove</A><BR>
|
||||
<A HREF="manual.html#pdf-os.rename">os.rename</A><BR>
|
||||
<A HREF="manual.html#pdf-os.setlocale">os.setlocale</A><BR>
|
||||
<A HREF="manual.html#pdf-os.time">os.time</A><BR>
|
||||
<A HREF="manual.html#pdf-os.tmpname">os.tmpname</A><BR>
|
||||
|
||||
<P>
|
||||
<A HREF="manual.html#6.3">package</A><BR>
|
||||
<A HREF="manual.html#pdf-package.config">package.config</A><BR>
|
||||
<A HREF="manual.html#pdf-package.cpath">package.cpath</A><BR>
|
||||
<A HREF="manual.html#pdf-package.loaded">package.loaded</A><BR>
|
||||
<A HREF="manual.html#pdf-package.loadlib">package.loadlib</A><BR>
|
||||
<A HREF="manual.html#pdf-package.path">package.path</A><BR>
|
||||
<A HREF="manual.html#pdf-package.preload">package.preload</A><BR>
|
||||
<A HREF="manual.html#pdf-package.searchers">package.searchers</A><BR>
|
||||
<A HREF="manual.html#pdf-package.searchpath">package.searchpath</A><BR>
|
||||
|
||||
<P>
|
||||
<A HREF="manual.html#6.4">string</A><BR>
|
||||
<A HREF="manual.html#pdf-string.byte">string.byte</A><BR>
|
||||
<A HREF="manual.html#pdf-string.char">string.char</A><BR>
|
||||
<A HREF="manual.html#pdf-string.dump">string.dump</A><BR>
|
||||
<A HREF="manual.html#pdf-string.find">string.find</A><BR>
|
||||
<A HREF="manual.html#pdf-string.format">string.format</A><BR>
|
||||
<A HREF="manual.html#pdf-string.gmatch">string.gmatch</A><BR>
|
||||
<A HREF="manual.html#pdf-string.gsub">string.gsub</A><BR>
|
||||
<A HREF="manual.html#pdf-string.len">string.len</A><BR>
|
||||
<A HREF="manual.html#pdf-string.lower">string.lower</A><BR>
|
||||
<A HREF="manual.html#pdf-string.match">string.match</A><BR>
|
||||
<A HREF="manual.html#pdf-string.pack">string.pack</A><BR>
|
||||
<A HREF="manual.html#pdf-string.packsize">string.packsize</A><BR>
|
||||
<A HREF="manual.html#pdf-string.rep">string.rep</A><BR>
|
||||
<A HREF="manual.html#pdf-string.reverse">string.reverse</A><BR>
|
||||
<A HREF="manual.html#pdf-string.sub">string.sub</A><BR>
|
||||
<A HREF="manual.html#pdf-string.unpack">string.unpack</A><BR>
|
||||
<A HREF="manual.html#pdf-string.upper">string.upper</A><BR>
|
||||
|
||||
<P>
|
||||
<A HREF="manual.html#6.6">table</A><BR>
|
||||
<A HREF="manual.html#pdf-table.concat">table.concat</A><BR>
|
||||
<A HREF="manual.html#pdf-table.insert">table.insert</A><BR>
|
||||
<A HREF="manual.html#pdf-table.move">table.move</A><BR>
|
||||
<A HREF="manual.html#pdf-table.pack">table.pack</A><BR>
|
||||
<A HREF="manual.html#pdf-table.remove">table.remove</A><BR>
|
||||
<A HREF="manual.html#pdf-table.sort">table.sort</A><BR>
|
||||
<A HREF="manual.html#pdf-table.unpack">table.unpack</A><BR>
|
||||
|
||||
<P>
|
||||
<A HREF="manual.html#6.5">utf8</A><BR>
|
||||
<A HREF="manual.html#pdf-utf8.char">utf8.char</A><BR>
|
||||
<A HREF="manual.html#pdf-utf8.charpattern">utf8.charpattern</A><BR>
|
||||
<A HREF="manual.html#pdf-utf8.codepoint">utf8.codepoint</A><BR>
|
||||
<A HREF="manual.html#pdf-utf8.codes">utf8.codes</A><BR>
|
||||
<A HREF="manual.html#pdf-utf8.len">utf8.len</A><BR>
|
||||
<A HREF="manual.html#pdf-utf8.offset">utf8.offset</A><BR>
|
||||
|
||||
<H3><A NAME="metamethods">metamethods</A></H3>
|
||||
<P>
|
||||
<A HREF="manual.html#2.4">__add</A><BR>
|
||||
<A HREF="manual.html#2.4">__band</A><BR>
|
||||
<A HREF="manual.html#2.4">__bnot</A><BR>
|
||||
<A HREF="manual.html#2.4">__bor</A><BR>
|
||||
<A HREF="manual.html#2.4">__bxor</A><BR>
|
||||
<A HREF="manual.html#2.4">__call</A><BR>
|
||||
<A HREF="manual.html#3.3.8">__close</A><BR>
|
||||
<A HREF="manual.html#2.4">__concat</A><BR>
|
||||
<A HREF="manual.html#2.4">__div</A><BR>
|
||||
<A HREF="manual.html#2.4">__eq</A><BR>
|
||||
<A HREF="manual.html#2.5.3">__gc</A><BR>
|
||||
<A HREF="manual.html#2.4">__idiv</A><BR>
|
||||
<A HREF="manual.html#2.4">__index</A><BR>
|
||||
<A HREF="manual.html#2.4">__le</A><BR>
|
||||
<A HREF="manual.html#2.4">__len</A><BR>
|
||||
<A HREF="manual.html#2.4">__lt</A><BR>
|
||||
<A HREF="manual.html#pdf-getmetatable">__metatable</A><BR>
|
||||
<A HREF="manual.html#2.4">__mod</A><BR>
|
||||
<A HREF="manual.html#2.5.4">__mode</A><BR>
|
||||
<A HREF="manual.html#2.4">__mul</A><BR>
|
||||
<A HREF="manual.html#luaL_newmetatable">__name</A><BR>
|
||||
<A HREF="manual.html#2.4">__newindex</A><BR>
|
||||
<A HREF="manual.html#pdf-pairs">__pairs</A><BR>
|
||||
<A HREF="manual.html#2.4">__pow</A><BR>
|
||||
<A HREF="manual.html#2.4">__shl</A><BR>
|
||||
<A HREF="manual.html#2.4">__shr</A><BR>
|
||||
<A HREF="manual.html#2.4">__sub</A><BR>
|
||||
<A HREF="manual.html#pdf-tostring">__tostring</A><BR>
|
||||
<A HREF="manual.html#2.4">__unm</A><BR>
|
||||
|
||||
<H3><A NAME="env">environment<BR>variables</A></H3>
|
||||
<P>
|
||||
<A HREF="manual.html#pdf-LUA_CPATH">LUA_CPATH</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_CPATH_5_4">LUA_CPATH_5_4</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_INIT">LUA_INIT</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_INIT_5_4">LUA_INIT_5_4</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_PATH">LUA_PATH</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_PATH_5_4">LUA_PATH_5_4</A><BR>
|
||||
|
||||
</TD>
|
||||
<TD>
|
||||
<H3><A NAME="api">C API</A></H3>
|
||||
<P>
|
||||
<A HREF="manual.html#lua_Alloc">lua_Alloc</A><BR>
|
||||
<A HREF="manual.html#lua_CFunction">lua_CFunction</A><BR>
|
||||
<A HREF="manual.html#lua_Debug">lua_Debug</A><BR>
|
||||
<A HREF="manual.html#lua_Hook">lua_Hook</A><BR>
|
||||
<A HREF="manual.html#lua_Integer">lua_Integer</A><BR>
|
||||
<A HREF="manual.html#lua_KContext">lua_KContext</A><BR>
|
||||
<A HREF="manual.html#lua_KFunction">lua_KFunction</A><BR>
|
||||
<A HREF="manual.html#lua_Number">lua_Number</A><BR>
|
||||
<A HREF="manual.html#lua_Reader">lua_Reader</A><BR>
|
||||
<A HREF="manual.html#lua_State">lua_State</A><BR>
|
||||
<A HREF="manual.html#lua_Unsigned">lua_Unsigned</A><BR>
|
||||
<A HREF="manual.html#lua_WarnFunction">lua_WarnFunction</A><BR>
|
||||
<A HREF="manual.html#lua_Writer">lua_Writer</A><BR>
|
||||
|
||||
<P>
|
||||
<A HREF="manual.html#lua_absindex">lua_absindex</A><BR>
|
||||
<A HREF="manual.html#lua_arith">lua_arith</A><BR>
|
||||
<A HREF="manual.html#lua_atpanic">lua_atpanic</A><BR>
|
||||
<A HREF="manual.html#lua_call">lua_call</A><BR>
|
||||
<A HREF="manual.html#lua_callk">lua_callk</A><BR>
|
||||
<A HREF="manual.html#lua_checkstack">lua_checkstack</A><BR>
|
||||
<A HREF="manual.html#lua_close">lua_close</A><BR>
|
||||
<A HREF="manual.html#lua_closeslot">lua_closeslot</A><BR>
|
||||
<A HREF="manual.html#lua_compare">lua_compare</A><BR>
|
||||
<A HREF="manual.html#lua_concat">lua_concat</A><BR>
|
||||
<A HREF="manual.html#lua_copy">lua_copy</A><BR>
|
||||
<A HREF="manual.html#lua_createtable">lua_createtable</A><BR>
|
||||
<A HREF="manual.html#lua_dump">lua_dump</A><BR>
|
||||
<A HREF="manual.html#lua_error">lua_error</A><BR>
|
||||
<A HREF="manual.html#lua_gc">lua_gc</A><BR>
|
||||
<A HREF="manual.html#lua_getallocf">lua_getallocf</A><BR>
|
||||
<A HREF="manual.html#lua_getextraspace">lua_getextraspace</A><BR>
|
||||
<A HREF="manual.html#lua_getfield">lua_getfield</A><BR>
|
||||
<A HREF="manual.html#lua_getglobal">lua_getglobal</A><BR>
|
||||
<A HREF="manual.html#lua_gethook">lua_gethook</A><BR>
|
||||
<A HREF="manual.html#lua_gethookcount">lua_gethookcount</A><BR>
|
||||
<A HREF="manual.html#lua_gethookmask">lua_gethookmask</A><BR>
|
||||
<A HREF="manual.html#lua_geti">lua_geti</A><BR>
|
||||
<A HREF="manual.html#lua_getinfo">lua_getinfo</A><BR>
|
||||
<A HREF="manual.html#lua_getiuservalue">lua_getiuservalue</A><BR>
|
||||
<A HREF="manual.html#lua_getlocal">lua_getlocal</A><BR>
|
||||
<A HREF="manual.html#lua_getmetatable">lua_getmetatable</A><BR>
|
||||
<A HREF="manual.html#lua_getstack">lua_getstack</A><BR>
|
||||
<A HREF="manual.html#lua_gettable">lua_gettable</A><BR>
|
||||
<A HREF="manual.html#lua_gettop">lua_gettop</A><BR>
|
||||
<A HREF="manual.html#lua_getupvalue">lua_getupvalue</A><BR>
|
||||
<A HREF="manual.html#lua_insert">lua_insert</A><BR>
|
||||
<A HREF="manual.html#lua_isboolean">lua_isboolean</A><BR>
|
||||
<A HREF="manual.html#lua_iscfunction">lua_iscfunction</A><BR>
|
||||
<A HREF="manual.html#lua_isfunction">lua_isfunction</A><BR>
|
||||
<A HREF="manual.html#lua_isinteger">lua_isinteger</A><BR>
|
||||
<A HREF="manual.html#lua_islightuserdata">lua_islightuserdata</A><BR>
|
||||
<A HREF="manual.html#lua_isnil">lua_isnil</A><BR>
|
||||
<A HREF="manual.html#lua_isnone">lua_isnone</A><BR>
|
||||
<A HREF="manual.html#lua_isnoneornil">lua_isnoneornil</A><BR>
|
||||
<A HREF="manual.html#lua_isnumber">lua_isnumber</A><BR>
|
||||
<A HREF="manual.html#lua_isstring">lua_isstring</A><BR>
|
||||
<A HREF="manual.html#lua_istable">lua_istable</A><BR>
|
||||
<A HREF="manual.html#lua_isthread">lua_isthread</A><BR>
|
||||
<A HREF="manual.html#lua_isuserdata">lua_isuserdata</A><BR>
|
||||
<A HREF="manual.html#lua_isyieldable">lua_isyieldable</A><BR>
|
||||
<A HREF="manual.html#lua_len">lua_len</A><BR>
|
||||
<A HREF="manual.html#lua_load">lua_load</A><BR>
|
||||
<A HREF="manual.html#lua_newstate">lua_newstate</A><BR>
|
||||
<A HREF="manual.html#lua_newtable">lua_newtable</A><BR>
|
||||
<A HREF="manual.html#lua_newthread">lua_newthread</A><BR>
|
||||
<A HREF="manual.html#lua_newuserdatauv">lua_newuserdatauv</A><BR>
|
||||
<A HREF="manual.html#lua_next">lua_next</A><BR>
|
||||
<A HREF="manual.html#lua_numbertointeger">lua_numbertointeger</A><BR>
|
||||
<A HREF="manual.html#lua_pcall">lua_pcall</A><BR>
|
||||
<A HREF="manual.html#lua_pcallk">lua_pcallk</A><BR>
|
||||
<A HREF="manual.html#lua_pop">lua_pop</A><BR>
|
||||
<A HREF="manual.html#lua_pushboolean">lua_pushboolean</A><BR>
|
||||
<A HREF="manual.html#lua_pushcclosure">lua_pushcclosure</A><BR>
|
||||
<A HREF="manual.html#lua_pushcfunction">lua_pushcfunction</A><BR>
|
||||
<A HREF="manual.html#lua_pushfstring">lua_pushfstring</A><BR>
|
||||
<A HREF="manual.html#lua_pushglobaltable">lua_pushglobaltable</A><BR>
|
||||
<A HREF="manual.html#lua_pushinteger">lua_pushinteger</A><BR>
|
||||
<A HREF="manual.html#lua_pushlightuserdata">lua_pushlightuserdata</A><BR>
|
||||
<A HREF="manual.html#lua_pushliteral">lua_pushliteral</A><BR>
|
||||
<A HREF="manual.html#lua_pushlstring">lua_pushlstring</A><BR>
|
||||
<A HREF="manual.html#lua_pushnil">lua_pushnil</A><BR>
|
||||
<A HREF="manual.html#lua_pushnumber">lua_pushnumber</A><BR>
|
||||
<A HREF="manual.html#lua_pushstring">lua_pushstring</A><BR>
|
||||
<A HREF="manual.html#lua_pushthread">lua_pushthread</A><BR>
|
||||
<A HREF="manual.html#lua_pushvalue">lua_pushvalue</A><BR>
|
||||
<A HREF="manual.html#lua_pushvfstring">lua_pushvfstring</A><BR>
|
||||
<A HREF="manual.html#lua_rawequal">lua_rawequal</A><BR>
|
||||
<A HREF="manual.html#lua_rawget">lua_rawget</A><BR>
|
||||
<A HREF="manual.html#lua_rawgeti">lua_rawgeti</A><BR>
|
||||
<A HREF="manual.html#lua_rawgetp">lua_rawgetp</A><BR>
|
||||
<A HREF="manual.html#lua_rawlen">lua_rawlen</A><BR>
|
||||
<A HREF="manual.html#lua_rawset">lua_rawset</A><BR>
|
||||
<A HREF="manual.html#lua_rawseti">lua_rawseti</A><BR>
|
||||
<A HREF="manual.html#lua_rawsetp">lua_rawsetp</A><BR>
|
||||
<A HREF="manual.html#lua_register">lua_register</A><BR>
|
||||
<A HREF="manual.html#lua_remove">lua_remove</A><BR>
|
||||
<A HREF="manual.html#lua_replace">lua_replace</A><BR>
|
||||
<A HREF="manual.html#lua_resetthread">lua_resetthread</A><BR>
|
||||
<A HREF="manual.html#lua_resume">lua_resume</A><BR>
|
||||
<A HREF="manual.html#lua_rotate">lua_rotate</A><BR>
|
||||
<A HREF="manual.html#lua_setallocf">lua_setallocf</A><BR>
|
||||
<A HREF="manual.html#lua_setfield">lua_setfield</A><BR>
|
||||
<A HREF="manual.html#lua_setglobal">lua_setglobal</A><BR>
|
||||
<A HREF="manual.html#lua_sethook">lua_sethook</A><BR>
|
||||
<A HREF="manual.html#lua_seti">lua_seti</A><BR>
|
||||
<A HREF="manual.html#lua_setiuservalue">lua_setiuservalue</A><BR>
|
||||
<A HREF="manual.html#lua_setlocal">lua_setlocal</A><BR>
|
||||
<A HREF="manual.html#lua_setmetatable">lua_setmetatable</A><BR>
|
||||
<A HREF="manual.html#lua_settable">lua_settable</A><BR>
|
||||
<A HREF="manual.html#lua_settop">lua_settop</A><BR>
|
||||
<A HREF="manual.html#lua_setupvalue">lua_setupvalue</A><BR>
|
||||
<A HREF="manual.html#lua_setwarnf">lua_setwarnf</A><BR>
|
||||
<A HREF="manual.html#lua_status">lua_status</A><BR>
|
||||
<A HREF="manual.html#lua_stringtonumber">lua_stringtonumber</A><BR>
|
||||
<A HREF="manual.html#lua_toboolean">lua_toboolean</A><BR>
|
||||
<A HREF="manual.html#lua_tocfunction">lua_tocfunction</A><BR>
|
||||
<A HREF="manual.html#lua_toclose">lua_toclose</A><BR>
|
||||
<A HREF="manual.html#lua_tointeger">lua_tointeger</A><BR>
|
||||
<A HREF="manual.html#lua_tointegerx">lua_tointegerx</A><BR>
|
||||
<A HREF="manual.html#lua_tolstring">lua_tolstring</A><BR>
|
||||
<A HREF="manual.html#lua_tonumber">lua_tonumber</A><BR>
|
||||
<A HREF="manual.html#lua_tonumberx">lua_tonumberx</A><BR>
|
||||
<A HREF="manual.html#lua_topointer">lua_topointer</A><BR>
|
||||
<A HREF="manual.html#lua_tostring">lua_tostring</A><BR>
|
||||
<A HREF="manual.html#lua_tothread">lua_tothread</A><BR>
|
||||
<A HREF="manual.html#lua_touserdata">lua_touserdata</A><BR>
|
||||
<A HREF="manual.html#lua_type">lua_type</A><BR>
|
||||
<A HREF="manual.html#lua_typename">lua_typename</A><BR>
|
||||
<A HREF="manual.html#lua_upvalueid">lua_upvalueid</A><BR>
|
||||
<A HREF="manual.html#lua_upvalueindex">lua_upvalueindex</A><BR>
|
||||
<A HREF="manual.html#lua_upvaluejoin">lua_upvaluejoin</A><BR>
|
||||
<A HREF="manual.html#lua_version">lua_version</A><BR>
|
||||
<A HREF="manual.html#lua_warning">lua_warning</A><BR>
|
||||
<A HREF="manual.html#lua_xmove">lua_xmove</A><BR>
|
||||
<A HREF="manual.html#lua_yield">lua_yield</A><BR>
|
||||
<A HREF="manual.html#lua_yieldk">lua_yieldk</A><BR>
|
||||
|
||||
</TD>
|
||||
<TD>
|
||||
<H3><A NAME="auxlib">auxiliary library</A></H3>
|
||||
<P>
|
||||
<A HREF="manual.html#luaL_Buffer">luaL_Buffer</A><BR>
|
||||
<A HREF="manual.html#luaL_Reg">luaL_Reg</A><BR>
|
||||
<A HREF="manual.html#luaL_Stream">luaL_Stream</A><BR>
|
||||
|
||||
<P>
|
||||
<A HREF="manual.html#luaL_addchar">luaL_addchar</A><BR>
|
||||
<A HREF="manual.html#luaL_addgsub">luaL_addgsub</A><BR>
|
||||
<A HREF="manual.html#luaL_addlstring">luaL_addlstring</A><BR>
|
||||
<A HREF="manual.html#luaL_addsize">luaL_addsize</A><BR>
|
||||
<A HREF="manual.html#luaL_addstring">luaL_addstring</A><BR>
|
||||
<A HREF="manual.html#luaL_addvalue">luaL_addvalue</A><BR>
|
||||
<A HREF="manual.html#luaL_argcheck">luaL_argcheck</A><BR>
|
||||
<A HREF="manual.html#luaL_argerror">luaL_argerror</A><BR>
|
||||
<A HREF="manual.html#luaL_argexpected">luaL_argexpected</A><BR>
|
||||
<A HREF="manual.html#luaL_buffaddr">luaL_buffaddr</A><BR>
|
||||
<A HREF="manual.html#luaL_buffinit">luaL_buffinit</A><BR>
|
||||
<A HREF="manual.html#luaL_buffinitsize">luaL_buffinitsize</A><BR>
|
||||
<A HREF="manual.html#luaL_bufflen">luaL_bufflen</A><BR>
|
||||
<A HREF="manual.html#luaL_buffsub">luaL_buffsub</A><BR>
|
||||
<A HREF="manual.html#luaL_callmeta">luaL_callmeta</A><BR>
|
||||
<A HREF="manual.html#luaL_checkany">luaL_checkany</A><BR>
|
||||
<A HREF="manual.html#luaL_checkinteger">luaL_checkinteger</A><BR>
|
||||
<A HREF="manual.html#luaL_checklstring">luaL_checklstring</A><BR>
|
||||
<A HREF="manual.html#luaL_checknumber">luaL_checknumber</A><BR>
|
||||
<A HREF="manual.html#luaL_checkoption">luaL_checkoption</A><BR>
|
||||
<A HREF="manual.html#luaL_checkstack">luaL_checkstack</A><BR>
|
||||
<A HREF="manual.html#luaL_checkstring">luaL_checkstring</A><BR>
|
||||
<A HREF="manual.html#luaL_checktype">luaL_checktype</A><BR>
|
||||
<A HREF="manual.html#luaL_checkudata">luaL_checkudata</A><BR>
|
||||
<A HREF="manual.html#luaL_checkversion">luaL_checkversion</A><BR>
|
||||
<A HREF="manual.html#luaL_dofile">luaL_dofile</A><BR>
|
||||
<A HREF="manual.html#luaL_dostring">luaL_dostring</A><BR>
|
||||
<A HREF="manual.html#luaL_error">luaL_error</A><BR>
|
||||
<A HREF="manual.html#luaL_execresult">luaL_execresult</A><BR>
|
||||
<A HREF="manual.html#luaL_fileresult">luaL_fileresult</A><BR>
|
||||
<A HREF="manual.html#luaL_getmetafield">luaL_getmetafield</A><BR>
|
||||
<A HREF="manual.html#luaL_getmetatable">luaL_getmetatable</A><BR>
|
||||
<A HREF="manual.html#luaL_getsubtable">luaL_getsubtable</A><BR>
|
||||
<A HREF="manual.html#luaL_gsub">luaL_gsub</A><BR>
|
||||
<A HREF="manual.html#luaL_len">luaL_len</A><BR>
|
||||
<A HREF="manual.html#luaL_loadbuffer">luaL_loadbuffer</A><BR>
|
||||
<A HREF="manual.html#luaL_loadbufferx">luaL_loadbufferx</A><BR>
|
||||
<A HREF="manual.html#luaL_loadfile">luaL_loadfile</A><BR>
|
||||
<A HREF="manual.html#luaL_loadfilex">luaL_loadfilex</A><BR>
|
||||
<A HREF="manual.html#luaL_loadstring">luaL_loadstring</A><BR>
|
||||
<A HREF="manual.html#luaL_newlib">luaL_newlib</A><BR>
|
||||
<A HREF="manual.html#luaL_newlibtable">luaL_newlibtable</A><BR>
|
||||
<A HREF="manual.html#luaL_newmetatable">luaL_newmetatable</A><BR>
|
||||
<A HREF="manual.html#luaL_newstate">luaL_newstate</A><BR>
|
||||
<A HREF="manual.html#luaL_openlibs">luaL_openlibs</A><BR>
|
||||
<A HREF="manual.html#luaL_opt">luaL_opt</A><BR>
|
||||
<A HREF="manual.html#luaL_optinteger">luaL_optinteger</A><BR>
|
||||
<A HREF="manual.html#luaL_optlstring">luaL_optlstring</A><BR>
|
||||
<A HREF="manual.html#luaL_optnumber">luaL_optnumber</A><BR>
|
||||
<A HREF="manual.html#luaL_optstring">luaL_optstring</A><BR>
|
||||
<A HREF="manual.html#luaL_prepbuffer">luaL_prepbuffer</A><BR>
|
||||
<A HREF="manual.html#luaL_prepbuffsize">luaL_prepbuffsize</A><BR>
|
||||
<A HREF="manual.html#luaL_pushfail">luaL_pushfail</A><BR>
|
||||
<A HREF="manual.html#luaL_pushresult">luaL_pushresult</A><BR>
|
||||
<A HREF="manual.html#luaL_pushresultsize">luaL_pushresultsize</A><BR>
|
||||
<A HREF="manual.html#luaL_ref">luaL_ref</A><BR>
|
||||
<A HREF="manual.html#luaL_requiref">luaL_requiref</A><BR>
|
||||
<A HREF="manual.html#luaL_setfuncs">luaL_setfuncs</A><BR>
|
||||
<A HREF="manual.html#luaL_setmetatable">luaL_setmetatable</A><BR>
|
||||
<A HREF="manual.html#luaL_testudata">luaL_testudata</A><BR>
|
||||
<A HREF="manual.html#luaL_tolstring">luaL_tolstring</A><BR>
|
||||
<A HREF="manual.html#luaL_traceback">luaL_traceback</A><BR>
|
||||
<A HREF="manual.html#luaL_typeerror">luaL_typeerror</A><BR>
|
||||
<A HREF="manual.html#luaL_typename">luaL_typename</A><BR>
|
||||
<A HREF="manual.html#luaL_unref">luaL_unref</A><BR>
|
||||
<A HREF="manual.html#luaL_where">luaL_where</A><BR>
|
||||
|
||||
<H3><A NAME="library">standard library</A></H3>
|
||||
<P>
|
||||
<A HREF="manual.html#pdf-luaopen_base">luaopen_base</A><BR>
|
||||
<A HREF="manual.html#pdf-luaopen_coroutine">luaopen_coroutine</A><BR>
|
||||
<A HREF="manual.html#pdf-luaopen_debug">luaopen_debug</A><BR>
|
||||
<A HREF="manual.html#pdf-luaopen_io">luaopen_io</A><BR>
|
||||
<A HREF="manual.html#pdf-luaopen_math">luaopen_math</A><BR>
|
||||
<A HREF="manual.html#pdf-luaopen_os">luaopen_os</A><BR>
|
||||
<A HREF="manual.html#pdf-luaopen_package">luaopen_package</A><BR>
|
||||
<A HREF="manual.html#pdf-luaopen_string">luaopen_string</A><BR>
|
||||
<A HREF="manual.html#pdf-luaopen_table">luaopen_table</A><BR>
|
||||
<A HREF="manual.html#pdf-luaopen_utf8">luaopen_utf8</A><BR>
|
||||
|
||||
<H3><A NAME="constants">constants</A></H3>
|
||||
<P>
|
||||
<A HREF="manual.html#pdf-LUA_ERRERR">LUA_ERRERR</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_ERRFILE">LUA_ERRFILE</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_ERRMEM">LUA_ERRMEM</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_ERRRUN">LUA_ERRRUN</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_ERRSYNTAX">LUA_ERRSYNTAX</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_HOOKCALL">LUA_HOOKCALL</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_HOOKCOUNT">LUA_HOOKCOUNT</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_HOOKLINE">LUA_HOOKLINE</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_HOOKRET">LUA_HOOKRET</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_HOOKTAILCALL">LUA_HOOKTAILCALL</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_LOADED_TABLE">LUA_LOADED_TABLE</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_MASKCALL">LUA_MASKCALL</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_MASKCOUNT">LUA_MASKCOUNT</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_MASKLINE">LUA_MASKLINE</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_MASKRET">LUA_MASKRET</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_MAXINTEGER">LUA_MAXINTEGER</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_MININTEGER">LUA_MININTEGER</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_MINSTACK">LUA_MINSTACK</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_MULTRET">LUA_MULTRET</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_NOREF">LUA_NOREF</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_OK">LUA_OK</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_OPADD">LUA_OPADD</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_OPBAND">LUA_OPBAND</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_OPBNOT">LUA_OPBNOT</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_OPBOR">LUA_OPBOR</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_OPBXOR">LUA_OPBXOR</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_OPDIV">LUA_OPDIV</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_OPEQ">LUA_OPEQ</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_OPIDIV">LUA_OPIDIV</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_OPLE">LUA_OPLE</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_OPLT">LUA_OPLT</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_OPMOD">LUA_OPMOD</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_OPMUL">LUA_OPMUL</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_OPPOW">LUA_OPPOW</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_OPSHL">LUA_OPSHL</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_OPSHR">LUA_OPSHR</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_OPSUB">LUA_OPSUB</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_OPUNM">LUA_OPUNM</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_PRELOAD_TABLE">LUA_PRELOAD_TABLE</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_REFNIL">LUA_REFNIL</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_REGISTRYINDEX">LUA_REGISTRYINDEX</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_RIDX_GLOBALS">LUA_RIDX_GLOBALS</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_RIDX_MAINTHREAD">LUA_RIDX_MAINTHREAD</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_TBOOLEAN">LUA_TBOOLEAN</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_TFUNCTION">LUA_TFUNCTION</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_TLIGHTUSERDATA">LUA_TLIGHTUSERDATA</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_TNIL">LUA_TNIL</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_TNONE">LUA_TNONE</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_TNUMBER">LUA_TNUMBER</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_TSTRING">LUA_TSTRING</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_TTABLE">LUA_TTABLE</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_TTHREAD">LUA_TTHREAD</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_TUSERDATA">LUA_TUSERDATA</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_USE_APICHECK">LUA_USE_APICHECK</A><BR>
|
||||
<A HREF="manual.html#pdf-LUA_YIELD">LUA_YIELD</A><BR>
|
||||
<A HREF="manual.html#pdf-LUAL_BUFFERSIZE">LUAL_BUFFERSIZE</A><BR>
|
||||
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
|
||||
<P CLASS="footer">
|
||||
Last update:
|
||||
Wed May 21 21:11:33 UTC 2025
|
||||
</P>
|
||||
<!--
|
||||
Last change: revised for Lua 5.4.8
|
||||
-->
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
||||
21
src/lua/lua-5.4.8/doc/index.css
Normal file
@@ -0,0 +1,21 @@
|
||||
ul {
|
||||
list-style-type: none ;
|
||||
}
|
||||
|
||||
ul.contents {
|
||||
padding: 0 ;
|
||||
}
|
||||
|
||||
table {
|
||||
border: none ;
|
||||
border-spacing: 0 ;
|
||||
border-collapse: collapse ;
|
||||
}
|
||||
|
||||
td {
|
||||
vertical-align: top ;
|
||||
padding: 0 ;
|
||||
text-align: left ;
|
||||
line-height: 1.25 ;
|
||||
width: 15% ;
|
||||
}
|
||||
BIN
src/lua/lua-5.4.8/doc/logo.gif
Normal file
|
After Width: | Height: | Size: 9.7 KiB |
155
src/lua/lua-5.4.8/doc/lua.1
Normal file
@@ -0,0 +1,155 @@
|
||||
.\" $Id: lua.man,v 1.14 2024/05/08 18:48:27 lhf Exp $
|
||||
.TH LUA 1 "$Date: 2024/05/08 18:48:27 $"
|
||||
.SH NAME
|
||||
lua \- Lua interpreter
|
||||
.SH SYNOPSIS
|
||||
.B lua
|
||||
[
|
||||
.I options
|
||||
]
|
||||
[
|
||||
.I script
|
||||
[
|
||||
.I args
|
||||
]
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
.B lua
|
||||
is the standalone Lua interpreter.
|
||||
It loads and executes Lua programs,
|
||||
either in textual source form or
|
||||
in precompiled binary form.
|
||||
(Precompiled binaries are output by
|
||||
.BR luac ,
|
||||
the Lua compiler.)
|
||||
.B lua
|
||||
can be used as a batch interpreter and also interactively.
|
||||
.LP
|
||||
After handling the
|
||||
.IR options ,
|
||||
the Lua program in file
|
||||
.I script
|
||||
is loaded and executed.
|
||||
The
|
||||
.I args
|
||||
are available to
|
||||
.I script
|
||||
as strings in a global table named
|
||||
.B arg
|
||||
and also as arguments to its main function.
|
||||
When called without arguments,
|
||||
.B lua
|
||||
behaves as
|
||||
.B "lua \-v \-i"
|
||||
if the standard input is a terminal,
|
||||
and as
|
||||
.B "lua \-"
|
||||
otherwise.
|
||||
.LP
|
||||
In interactive mode,
|
||||
.B lua
|
||||
prompts the user,
|
||||
reads lines from the standard input,
|
||||
and executes them as they are read.
|
||||
If the line contains an expression,
|
||||
then the line is evaluated and the result is printed.
|
||||
If a line does not contain a complete statement,
|
||||
then a secondary prompt is displayed and
|
||||
lines are read until a complete statement is formed or
|
||||
a syntax error is found.
|
||||
.LP
|
||||
Before handling command line options and scripts,
|
||||
.B lua
|
||||
checks the contents of the environment variables
|
||||
.B LUA_INIT_5_4
|
||||
and
|
||||
.BR LUA_INIT ,
|
||||
in that order.
|
||||
If the contents are of the form
|
||||
.RI '@ filename ',
|
||||
then
|
||||
.I filename
|
||||
is executed.
|
||||
Otherwise, the contents are assumed to be a Lua statement and is executed.
|
||||
When
|
||||
.B LUA_INIT_5_4
|
||||
is defined,
|
||||
.B LUA_INIT
|
||||
is ignored.
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.BI \-e " stat"
|
||||
execute statement
|
||||
.IR stat .
|
||||
.TP
|
||||
.B \-i
|
||||
enter interactive mode after executing
|
||||
.IR script .
|
||||
.TP
|
||||
.BI \-l " mod"
|
||||
require library
|
||||
.I mod
|
||||
into global
|
||||
.IR mod .
|
||||
.TP
|
||||
.BI \-l " g=mod"
|
||||
require library
|
||||
.I mod
|
||||
into global
|
||||
.IR g .
|
||||
.TP
|
||||
.B \-v
|
||||
show version information.
|
||||
.TP
|
||||
.B \-E
|
||||
ignore environment variables.
|
||||
.TP
|
||||
.B \-W
|
||||
turn warnings on.
|
||||
.TP
|
||||
.B \-\-
|
||||
stop handling options.
|
||||
.TP
|
||||
.B \-
|
||||
stop handling options and execute the standard input as a file.
|
||||
.SH ENVIRONMENT VARIABLES
|
||||
The following environment variables affect the execution of
|
||||
.BR lua .
|
||||
When defined,
|
||||
the version-specific variants take priority
|
||||
and the version-neutral variants are ignored.
|
||||
.TP
|
||||
.B LUA_INIT, LUA_INIT_5_4
|
||||
Code to be executed before command line options and scripts.
|
||||
.TP
|
||||
.B LUA_PATH, LUA_PATH_5_4
|
||||
Initial value of package.path,
|
||||
the path used by require to search for Lua loaders.
|
||||
.TP
|
||||
.B LUA_CPATH, LUA_CPATH_5_4
|
||||
Initial value of package.cpath,
|
||||
the path used by require to search for C loaders.
|
||||
.SH EXIT STATUS
|
||||
If a script calls os.exit,
|
||||
then
|
||||
.B lua
|
||||
exits with the given exit status.
|
||||
Otherwise,
|
||||
.B lua
|
||||
exits
|
||||
with EXIT_SUCCESS (0 on POSIX systems) if there were no errors
|
||||
and
|
||||
with EXIT_FAILURE (1 on POSIX systems) if there were errors.
|
||||
Errors raised in interactive mode do not cause exits.
|
||||
.SH DIAGNOSTICS
|
||||
Error messages should be self explanatory.
|
||||
.SH "SEE ALSO"
|
||||
.BR luac (1)
|
||||
.br
|
||||
The documentation at lua.org,
|
||||
especially section 7 of the reference manual.
|
||||
.SH AUTHORS
|
||||
R. Ierusalimschy,
|
||||
L. H. de Figueiredo,
|
||||
W. Celes
|
||||
.\" EOF
|
||||
162
src/lua/lua-5.4.8/doc/lua.css
Normal file
@@ -0,0 +1,162 @@
|
||||
html {
|
||||
background-color: #F8F8F8 ;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: #FFFFFF ;
|
||||
color: #000000 ;
|
||||
font-family: Helvetica, Arial, sans-serif ;
|
||||
text-align: justify ;
|
||||
line-height: 1.25 ;
|
||||
margin: 16px auto ;
|
||||
padding: 32px ;
|
||||
border: solid #ccc 1px ;
|
||||
border-radius: 20px ;
|
||||
max-width: 70em ;
|
||||
width: 90% ;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4 {
|
||||
color: #000080 ;
|
||||
font-family: Verdana, Geneva, sans-serif ;
|
||||
font-weight: normal ;
|
||||
font-style: normal ;
|
||||
text-align: left ;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 28pt ;
|
||||
}
|
||||
|
||||
h1 img {
|
||||
vertical-align: text-bottom ;
|
||||
}
|
||||
|
||||
h2:before {
|
||||
content: "\2756" ;
|
||||
padding-right: 0.5em ;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none ;
|
||||
}
|
||||
|
||||
a:link {
|
||||
color: #000080 ;
|
||||
}
|
||||
|
||||
a:link:hover, a:visited:hover {
|
||||
background-color: #D0D0FF ;
|
||||
color: #000080 ;
|
||||
border-radius: 4px ;
|
||||
}
|
||||
|
||||
a:link:active, a:visited:active {
|
||||
color: #FF0000 ;
|
||||
}
|
||||
|
||||
div.menubar {
|
||||
padding-bottom: 0.5em ;
|
||||
}
|
||||
|
||||
p.menubar {
|
||||
margin-left: 2.5em ;
|
||||
}
|
||||
|
||||
.menubar a:hover {
|
||||
margin: -3px -3px -3px -3px ;
|
||||
padding: 3px 3px 3px 3px ;
|
||||
border-radius: 4px ;
|
||||
}
|
||||
|
||||
:target {
|
||||
background-color: #F0F0F0 ;
|
||||
margin: -8px ;
|
||||
padding: 8px ;
|
||||
border-radius: 8px ;
|
||||
outline: none ;
|
||||
}
|
||||
|
||||
hr {
|
||||
display: none ;
|
||||
}
|
||||
|
||||
table hr {
|
||||
background-color: #a0a0a0 ;
|
||||
color: #a0a0a0 ;
|
||||
border: 0 ;
|
||||
height: 1px ;
|
||||
display: block ;
|
||||
}
|
||||
|
||||
.footer {
|
||||
color: gray ;
|
||||
font-size: x-small ;
|
||||
text-transform: lowercase ;
|
||||
}
|
||||
|
||||
input[type=text] {
|
||||
border: solid #a0a0a0 2px ;
|
||||
border-radius: 2em ;
|
||||
background-image: url('images/search.png') ;
|
||||
background-repeat: no-repeat ;
|
||||
background-position: 4px center ;
|
||||
padding-left: 20px ;
|
||||
height: 2em ;
|
||||
}
|
||||
|
||||
pre.session {
|
||||
background-color: #F8F8F8 ;
|
||||
padding: 1em ;
|
||||
border-radius: 8px ;
|
||||
}
|
||||
|
||||
table {
|
||||
border: none ;
|
||||
border-spacing: 0 ;
|
||||
border-collapse: collapse ;
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 0 ;
|
||||
margin: 0 ;
|
||||
}
|
||||
|
||||
td.gutter {
|
||||
width: 4% ;
|
||||
}
|
||||
|
||||
table.columns td {
|
||||
vertical-align: top ;
|
||||
padding-bottom: 1em ;
|
||||
text-align: justify ;
|
||||
line-height: 1.25 ;
|
||||
}
|
||||
|
||||
table.book td {
|
||||
vertical-align: top ;
|
||||
}
|
||||
|
||||
table.book td.cover {
|
||||
padding-right: 1em ;
|
||||
}
|
||||
|
||||
table.book img {
|
||||
border: solid #000080 1px ;
|
||||
border-radius: 2px ;
|
||||
}
|
||||
|
||||
table.book span {
|
||||
font-size: small ;
|
||||
text-align: left ;
|
||||
display: block ;
|
||||
margin-top: 0.25em ;
|
||||
}
|
||||
|
||||
p.logos a:link:hover, p.logos a:visited:hover {
|
||||
background-color: inherit ;
|
||||
}
|
||||
|
||||
img {
|
||||
background-color: white ;
|
||||
}
|
||||
118
src/lua/lua-5.4.8/doc/luac.1
Normal file
@@ -0,0 +1,118 @@
|
||||
.\" $Id: luac.man,v 1.29 2011/11/16 13:53:40 lhf Exp $
|
||||
.TH LUAC 1 "$Date: 2011/11/16 13:53:40 $"
|
||||
.SH NAME
|
||||
luac \- Lua compiler
|
||||
.SH SYNOPSIS
|
||||
.B luac
|
||||
[
|
||||
.I options
|
||||
] [
|
||||
.I filenames
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
.B luac
|
||||
is the Lua compiler.
|
||||
It translates programs written in the Lua programming language
|
||||
into binary files containing precompiled chunks
|
||||
that can be later loaded and executed.
|
||||
.LP
|
||||
The main advantages of precompiling chunks are:
|
||||
faster loading,
|
||||
protecting source code from accidental user changes,
|
||||
and
|
||||
off-line syntax checking.
|
||||
Precompiling does not imply faster execution
|
||||
because in Lua chunks are always compiled into bytecodes before being executed.
|
||||
.B luac
|
||||
simply allows those bytecodes to be saved in a file for later execution.
|
||||
Precompiled chunks are not necessarily smaller than the corresponding source.
|
||||
The main goal in precompiling is faster loading.
|
||||
.LP
|
||||
In the command line,
|
||||
you can mix
|
||||
text files containing Lua source and
|
||||
binary files containing precompiled chunks.
|
||||
.B luac
|
||||
produces a single output file containing the combined bytecodes
|
||||
for all files given.
|
||||
Executing the combined file is equivalent to executing the given files.
|
||||
By default,
|
||||
the output file is named
|
||||
.BR luac.out ,
|
||||
but you can change this with the
|
||||
.B \-o
|
||||
option.
|
||||
.LP
|
||||
Precompiled chunks are
|
||||
.I not
|
||||
portable across different architectures.
|
||||
Moreover,
|
||||
the internal format of precompiled chunks
|
||||
is likely to change when a new version of Lua is released.
|
||||
Make sure you save the source files of all Lua programs that you precompile.
|
||||
.LP
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.B \-l
|
||||
produce a listing of the compiled bytecode for Lua's virtual machine.
|
||||
Listing bytecodes is useful to learn about Lua's virtual machine.
|
||||
If no files are given, then
|
||||
.B luac
|
||||
loads
|
||||
.B luac.out
|
||||
and lists its contents.
|
||||
Use
|
||||
.B \-l \-l
|
||||
for a full listing.
|
||||
.TP
|
||||
.BI \-o " file"
|
||||
output to
|
||||
.IR file ,
|
||||
instead of the default
|
||||
.BR luac.out .
|
||||
(You can use
|
||||
.B "'\-'"
|
||||
for standard output,
|
||||
but not on platforms that open standard output in text mode.)
|
||||
The output file may be one of the given files because
|
||||
all files are loaded before the output file is written.
|
||||
Be careful not to overwrite precious files.
|
||||
.TP
|
||||
.B \-p
|
||||
load files but do not generate any output file.
|
||||
Used mainly for syntax checking and for testing precompiled chunks:
|
||||
corrupted files will probably generate errors when loaded.
|
||||
If no files are given, then
|
||||
.B luac
|
||||
loads
|
||||
.B luac.out
|
||||
and tests its contents.
|
||||
No messages are displayed if the file loads without errors.
|
||||
.TP
|
||||
.B \-s
|
||||
strip debug information before writing the output file.
|
||||
This saves some space in very large chunks,
|
||||
but if errors occur when running a stripped chunk,
|
||||
then the error messages may not contain the full information they usually do.
|
||||
In particular,
|
||||
line numbers and names of local variables are lost.
|
||||
.TP
|
||||
.B \-v
|
||||
show version information.
|
||||
.TP
|
||||
.B \-\-
|
||||
stop handling options.
|
||||
.TP
|
||||
.B \-
|
||||
stop handling options and process standard input.
|
||||
.SH "SEE ALSO"
|
||||
.BR lua (1)
|
||||
.br
|
||||
The documentation at lua.org.
|
||||
.SH DIAGNOSTICS
|
||||
Error messages should be self explanatory.
|
||||
.SH AUTHORS
|
||||
R. Ierusalimschy,
|
||||
L. H. de Figueiredo,
|
||||
W. Celes
|
||||
.\" EOF
|
||||
21
src/lua/lua-5.4.8/doc/manual.css
Normal file
@@ -0,0 +1,21 @@
|
||||
h3 code {
|
||||
font-family: inherit ;
|
||||
font-size: inherit ;
|
||||
}
|
||||
|
||||
pre, code {
|
||||
font-size: 12pt ;
|
||||
}
|
||||
|
||||
span.apii {
|
||||
color: gray ;
|
||||
float: right ;
|
||||
font-family: inherit ;
|
||||
font-style: normal ;
|
||||
font-size: small ;
|
||||
}
|
||||
|
||||
h2:before {
|
||||
content: "" ;
|
||||
padding-right: 0em ;
|
||||
}
|
||||
12060
src/lua/lua-5.4.8/doc/manual.html
Normal file
339
src/lua/lua-5.4.8/doc/readme.html
Normal file
@@ -0,0 +1,339 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>Lua 5.4 readme</TITLE>
|
||||
<LINK REL="stylesheet" TYPE="text/css" HREF="lua.css">
|
||||
<META HTTP-EQUIV="content-type" CONTENT="text/html; charset=iso-8859-1">
|
||||
<STYLE TYPE="text/css">
|
||||
blockquote, .display {
|
||||
border: solid #a0a0a0 2px ;
|
||||
border-radius: 8px ;
|
||||
padding: 1em ;
|
||||
margin: 0px ;
|
||||
}
|
||||
|
||||
.display {
|
||||
word-spacing: 0.25em ;
|
||||
}
|
||||
|
||||
dl.display dd {
|
||||
padding-bottom: 0.2em ;
|
||||
}
|
||||
|
||||
tt, kbd, code {
|
||||
font-size: 12pt ;
|
||||
}
|
||||
</STYLE>
|
||||
</HEAD>
|
||||
|
||||
<BODY>
|
||||
|
||||
<H1>
|
||||
<A HREF="https://www.lua.org/"><IMG SRC="logo.gif" ALT="Lua"></A>
|
||||
Welcome to Lua 5.4
|
||||
</H1>
|
||||
|
||||
<DIV CLASS="menubar">
|
||||
<A HREF="#about">about</A>
|
||||
·
|
||||
<A HREF="#install">installation</A>
|
||||
·
|
||||
<A HREF="#changes">changes</A>
|
||||
·
|
||||
<A HREF="#license">license</A>
|
||||
·
|
||||
<A HREF="contents.html">reference manual</A>
|
||||
</DIV>
|
||||
|
||||
<H2><A NAME="about">About Lua</A></H2>
|
||||
<P>
|
||||
Lua is a powerful, efficient, lightweight, embeddable scripting language
|
||||
developed by a
|
||||
<A HREF="https://www.lua.org/authors.html">team</A>
|
||||
at
|
||||
<A HREF="https://www.puc-rio.br/">PUC-Rio</A>,
|
||||
the Pontifical Catholic University of Rio de Janeiro in Brazil.
|
||||
Lua is
|
||||
<A HREF="#license">free software</A>
|
||||
used in
|
||||
<A HREF="https://www.lua.org/uses.html">many products and projects</A>
|
||||
around the world.
|
||||
|
||||
<P>
|
||||
Lua's
|
||||
<A HREF="https://www.lua.org/">official website</A>
|
||||
provides complete information
|
||||
about Lua,
|
||||
including
|
||||
an
|
||||
<A HREF="https://www.lua.org/about.html">executive summary</A>,
|
||||
tips on
|
||||
<A HREF="https://www.lua.org/start.html">getting started</A>,
|
||||
and
|
||||
updated
|
||||
<A HREF="https://www.lua.org/docs.html">documentation</A>,
|
||||
especially the
|
||||
<A HREF="https://www.lua.org/manual/5.4/">reference manual</A>,
|
||||
which may differ slightly from the
|
||||
<A HREF="contents.html">local copy</A>
|
||||
distributed in this package.
|
||||
|
||||
<H2><A NAME="install">Installing Lua</A></H2>
|
||||
<P>
|
||||
Lua is distributed in
|
||||
<A HREF="https://www.lua.org/ftp/">source</A>
|
||||
form.
|
||||
You need to build it before using it.
|
||||
Building Lua should be straightforward
|
||||
because
|
||||
Lua is implemented in pure ANSI C and compiles unmodified in all known
|
||||
platforms that have an ANSI C compiler.
|
||||
Lua also compiles unmodified as C++.
|
||||
The instructions given below for building Lua are for Unix-like platforms,
|
||||
such as Linux and macOS.
|
||||
See also
|
||||
<A HREF="#other">instructions for other systems</A>
|
||||
and
|
||||
<A HREF="#customization">customization options</A>.
|
||||
|
||||
<P>
|
||||
If you don't have the time or the inclination to compile Lua yourself,
|
||||
get a binary from
|
||||
<A HREF="https://luabinaries.sourceforge.net">LuaBinaries</A>.
|
||||
|
||||
<H3>Building Lua</H3>
|
||||
<P>
|
||||
In most common Unix-like platforms, simply do "<KBD>make</KBD>".
|
||||
Here are the details.
|
||||
|
||||
<OL>
|
||||
<LI>
|
||||
Open a terminal window and move to
|
||||
the top-level directory, which is named <TT>lua-5.4.8</TT>.
|
||||
The <TT>Makefile</TT> there controls both the build process and the installation process.
|
||||
<P>
|
||||
<LI>
|
||||
Do "<KBD>make</KBD>". The <TT>Makefile</TT> will guess your platform and build Lua for it.
|
||||
<P>
|
||||
<LI>
|
||||
If the guess failed, do "<KBD>make help</KBD>" and see if your platform is listed.
|
||||
The platforms currently supported are:
|
||||
<P>
|
||||
<P CLASS="display">
|
||||
guess aix bsd c89 freebsd generic ios linux linux-readline macosx mingw posix solaris
|
||||
</P>
|
||||
<P>
|
||||
If your platform is listed, just do "<KBD>make xxx</KBD>", where xxx
|
||||
is your platform name.
|
||||
<P>
|
||||
If your platform is not listed, try the closest one or posix, generic,
|
||||
c89, in this order.
|
||||
<P>
|
||||
<LI>
|
||||
The compilation takes only a few moments
|
||||
and produces three files in the <TT>src</TT> directory:
|
||||
lua (the interpreter),
|
||||
luac (the compiler),
|
||||
and liblua.a (the library).
|
||||
<P>
|
||||
<LI>
|
||||
To check that Lua has been built correctly, do "<KBD>make test</KBD>"
|
||||
after building Lua. This will run the interpreter and print its version.
|
||||
</OL>
|
||||
<P>
|
||||
If you're running Linux, try "<KBD>make linux-readline</KBD>" to build the interactive Lua interpreter with handy line-editing and history capabilities.
|
||||
If you get compilation errors,
|
||||
make sure you have installed the <TT>readline</TT> development package
|
||||
(which is probably named <TT>libreadline-dev</TT> or <TT>readline-devel</TT>).
|
||||
If you get link errors after that,
|
||||
then try "<KBD>make linux-readline MYLIBS=-ltermcap</KBD>".
|
||||
|
||||
<H3>Installing Lua</H3>
|
||||
<P>
|
||||
Once you have built Lua, you may want to install it in an official
|
||||
place in your system. In this case, do "<KBD>make install</KBD>". The official
|
||||
place and the way to install files are defined in the <TT>Makefile</TT>. You'll
|
||||
probably need the right permissions to install files, and so may need to do "<KBD>sudo make install</KBD>".
|
||||
|
||||
<P>
|
||||
To build and install Lua in one step, do "<KBD>make all install</KBD>",
|
||||
or "<KBD>make xxx install</KBD>",
|
||||
where xxx is your platform name.
|
||||
|
||||
<P>
|
||||
To install Lua locally after building it, do "<KBD>make local</KBD>".
|
||||
This will create a directory <TT>install</TT> with subdirectories
|
||||
<TT>bin</TT>, <TT>include</TT>, <TT>lib</TT>, <TT>man</TT>, <TT>share</TT>,
|
||||
and install Lua as listed below.
|
||||
|
||||
To install Lua locally, but in some other directory, do
|
||||
"<KBD>make install INSTALL_TOP=xxx</KBD>", where xxx is your chosen directory.
|
||||
The installation starts in the <TT>src</TT> and <TT>doc</TT> directories,
|
||||
so take care if <TT>INSTALL_TOP</TT> is not an absolute path.
|
||||
|
||||
<DL CLASS="display">
|
||||
<DT>
|
||||
bin:
|
||||
<DD>
|
||||
lua luac
|
||||
<DT>
|
||||
include:
|
||||
<DD>
|
||||
lua.h luaconf.h lualib.h lauxlib.h lua.hpp
|
||||
<DT>
|
||||
lib:
|
||||
<DD>
|
||||
liblua.a
|
||||
<DT>
|
||||
man/man1:
|
||||
<DD>
|
||||
lua.1 luac.1
|
||||
</DL>
|
||||
|
||||
<P>
|
||||
These are the only directories you need for development.
|
||||
If you only want to run Lua programs,
|
||||
you only need the files in <TT>bin</TT> and <TT>man</TT>.
|
||||
The files in <TT>include</TT> and <TT>lib</TT> are needed for
|
||||
embedding Lua in C or C++ programs.
|
||||
|
||||
<H3><A NAME="customization">Customization</A></H3>
|
||||
<P>
|
||||
Three kinds of things can be customized by editing a file:
|
||||
<UL>
|
||||
<LI> Where and how to install Lua — edit <TT>Makefile</TT>.
|
||||
<LI> How to build Lua — edit <TT>src/Makefile</TT>.
|
||||
<LI> Lua features — edit <TT>src/luaconf.h</TT>.
|
||||
</UL>
|
||||
|
||||
<P>
|
||||
You don't actually need to edit the Makefiles because you may set the
|
||||
relevant variables in the command line when invoking make.
|
||||
Nevertheless, it's probably best to edit and save the Makefiles to
|
||||
record the changes you've made.
|
||||
|
||||
<P>
|
||||
On the other hand, if you need to customize some Lua features,
|
||||
edit <TT>src/luaconf.h</TT> before building and installing Lua.
|
||||
The edited file will be the one installed, and
|
||||
it will be used by any Lua clients that you build, to ensure consistency.
|
||||
Further customization is available to experts by editing the Lua sources.
|
||||
|
||||
<H3><A NAME="other">Building Lua on other systems</A></H3>
|
||||
<P>
|
||||
If you're not using the usual Unix tools, then the instructions for
|
||||
building Lua depend on the compiler you use. You'll need to create
|
||||
projects (or whatever your compiler uses) for building the library,
|
||||
the interpreter, and the compiler, as follows:
|
||||
|
||||
<DL CLASS="display">
|
||||
<DT>
|
||||
library:
|
||||
<DD>
|
||||
lapi.c lcode.c lctype.c ldebug.c ldo.c ldump.c lfunc.c lgc.c llex.c lmem.c lobject.c lopcodes.c lparser.c lstate.c lstring.c ltable.c ltm.c lundump.c lvm.c lzio.c
|
||||
lauxlib.c lbaselib.c lcorolib.c ldblib.c liolib.c lmathlib.c loadlib.c loslib.c lstrlib.c ltablib.c lutf8lib.c linit.c
|
||||
<DT>
|
||||
interpreter:
|
||||
<DD>
|
||||
library, lua.c
|
||||
<DT>
|
||||
compiler:
|
||||
<DD>
|
||||
library, luac.c
|
||||
</DL>
|
||||
|
||||
<P>
|
||||
To use Lua as a library in your own programs, you need to know how to
|
||||
create and use libraries with your compiler. Moreover, to dynamically load
|
||||
C libraries for Lua, you'll need to know how to create dynamic libraries
|
||||
and you'll need to make sure that the Lua API functions are accessible to
|
||||
those dynamic libraries — but <EM>don't</EM> link the Lua library
|
||||
into each dynamic library. For Unix, we recommend that the Lua library
|
||||
be linked statically into the host program and its symbols exported for
|
||||
dynamic linking; <TT>src/Makefile</TT> does this for the Lua interpreter.
|
||||
For Windows, we recommend that the Lua library be a DLL.
|
||||
In all cases, the compiler luac should be linked statically.
|
||||
|
||||
<P>
|
||||
As mentioned above, you may edit <TT>src/luaconf.h</TT> to customize
|
||||
some features before building Lua.
|
||||
|
||||
<H2><A NAME="changes">Changes since Lua 5.3</A></H2>
|
||||
<P>
|
||||
Here are the main changes introduced in Lua 5.4.
|
||||
The
|
||||
<A HREF="contents.html">reference manual</A>
|
||||
lists the
|
||||
<A HREF="manual.html#8">incompatibilities</A> that had to be introduced.
|
||||
|
||||
<H3>Main changes</H3>
|
||||
<UL>
|
||||
<LI> new generational mode for garbage collection
|
||||
<LI> to-be-closed variables
|
||||
<LI> const variables
|
||||
<LI> userdata can have multiple user values
|
||||
<LI> new implementation for math.random
|
||||
<LI> warning system
|
||||
<LI> debug information about function arguments and returns
|
||||
<LI> new semantics for the integer 'for' loop
|
||||
<LI> optional 'init' argument to 'string.gmatch'
|
||||
<LI> new functions 'lua_resetthread' and 'coroutine.close'
|
||||
<LI> string-to-number coercions moved to the string library
|
||||
<LI> allocation function allowed to fail when shrinking a memory block
|
||||
<LI> new format '%p' in 'string.format'
|
||||
<LI> utf8 library accepts codepoints up to 2^31
|
||||
</UL>
|
||||
|
||||
<H2><A NAME="license">License</A></H2>
|
||||
<P>
|
||||
<A HREF="https://opensource.org/osd">
|
||||
<IMG SRC="OSIApproved_100X125.png" ALIGN="right" ALT="[Open Source Initiative Approved License]" STYLE="padding-left: 1em" WIDTH=50>
|
||||
</A>
|
||||
Lua is free software distributed under the terms of the
|
||||
<A HREF="https://opensource.org/license/mit">MIT license</A>
|
||||
reproduced below;
|
||||
it may be used for any purpose, including commercial purposes,
|
||||
at absolutely no cost without having to ask us.
|
||||
|
||||
The only requirement is that if you do use Lua,
|
||||
then you should give us credit by including the appropriate copyright notice somewhere in your product or its documentation.
|
||||
|
||||
For details, see the
|
||||
<A HREF="https://www.lua.org/license.html">license page</A>.
|
||||
|
||||
<BLOCKQUOTE STYLE="padding-bottom: 0em">
|
||||
Copyright © 1994–2025 Lua.org, PUC-Rio.
|
||||
|
||||
<P>
|
||||
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:
|
||||
|
||||
<P>
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
<P>
|
||||
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.
|
||||
</BLOCKQUOTE>
|
||||
<P>
|
||||
|
||||
<P CLASS="footer">
|
||||
Last update:
|
||||
Wed May 21 21:12:01 UTC 2025
|
||||
</P>
|
||||
<!--
|
||||
Last change: revised for Lua 5.4.8
|
||||
-->
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
||||
225
src/lua/lua-5.4.8/src/Makefile
Normal file
@@ -0,0 +1,225 @@
|
||||
# Makefile for building Lua
|
||||
# See ../doc/readme.html for installation and customization instructions.
|
||||
|
||||
# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT =======================
|
||||
|
||||
# Your platform. See PLATS for possible values.
|
||||
PLAT= guess
|
||||
|
||||
CC= gcc -std=gnu99
|
||||
CFLAGS= -O2 -Wall -Wextra -DLUA_COMPAT_5_3 $(SYSCFLAGS) $(MYCFLAGS)
|
||||
LDFLAGS= $(SYSLDFLAGS) $(MYLDFLAGS)
|
||||
LIBS= -lm $(SYSLIBS) $(MYLIBS)
|
||||
|
||||
AR= ar rcu
|
||||
RANLIB= ranlib
|
||||
RM= rm -f
|
||||
UNAME= uname
|
||||
|
||||
SYSCFLAGS=
|
||||
SYSLDFLAGS=
|
||||
SYSLIBS=
|
||||
|
||||
MYCFLAGS=
|
||||
MYLDFLAGS=
|
||||
MYLIBS=
|
||||
MYOBJS=
|
||||
|
||||
# Special flags for compiler modules; -Os reduces code size.
|
||||
CMCFLAGS=
|
||||
|
||||
# == END OF USER SETTINGS -- NO NEED TO CHANGE ANYTHING BELOW THIS LINE =======
|
||||
|
||||
PLATS= guess aix bsd c89 freebsd generic ios linux linux-readline macosx mingw posix solaris
|
||||
|
||||
LUA_A= liblua.a
|
||||
CORE_O= lapi.o lcode.o lctype.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o lundump.o lvm.o lzio.o
|
||||
LIB_O= lauxlib.o lbaselib.o lcorolib.o ldblib.o liolib.o lmathlib.o loadlib.o loslib.o lstrlib.o ltablib.o lutf8lib.o linit.o
|
||||
BASE_O= $(CORE_O) $(LIB_O) $(MYOBJS)
|
||||
|
||||
LUA_T= lua
|
||||
LUA_O= lua.o
|
||||
|
||||
LUAC_T= luac
|
||||
LUAC_O= luac.o
|
||||
|
||||
ALL_O= $(BASE_O) $(LUA_O) $(LUAC_O)
|
||||
ALL_T= $(LUA_A) $(LUA_T) $(LUAC_T)
|
||||
ALL_A= $(LUA_A)
|
||||
|
||||
# Targets start here.
|
||||
default: $(PLAT)
|
||||
|
||||
all: $(ALL_T)
|
||||
|
||||
o: $(ALL_O)
|
||||
|
||||
a: $(ALL_A)
|
||||
|
||||
$(LUA_A): $(BASE_O)
|
||||
$(AR) $@ $(BASE_O)
|
||||
$(RANLIB) $@
|
||||
|
||||
$(LUA_T): $(LUA_O) $(LUA_A)
|
||||
$(CC) -o $@ $(LDFLAGS) $(LUA_O) $(LUA_A) $(LIBS)
|
||||
|
||||
$(LUAC_T): $(LUAC_O) $(LUA_A)
|
||||
$(CC) -o $@ $(LDFLAGS) $(LUAC_O) $(LUA_A) $(LIBS)
|
||||
|
||||
test:
|
||||
./$(LUA_T) -v
|
||||
|
||||
clean:
|
||||
$(RM) $(ALL_T) $(ALL_O)
|
||||
|
||||
depend:
|
||||
@$(CC) $(CFLAGS) -MM l*.c
|
||||
|
||||
echo:
|
||||
@echo "PLAT= $(PLAT)"
|
||||
@echo "CC= $(CC)"
|
||||
@echo "CFLAGS= $(CFLAGS)"
|
||||
@echo "LDFLAGS= $(LDFLAGS)"
|
||||
@echo "LIBS= $(LIBS)"
|
||||
@echo "AR= $(AR)"
|
||||
@echo "RANLIB= $(RANLIB)"
|
||||
@echo "RM= $(RM)"
|
||||
@echo "UNAME= $(UNAME)"
|
||||
|
||||
# Convenience targets for popular platforms.
|
||||
ALL= all
|
||||
|
||||
help:
|
||||
@echo "Do 'make PLATFORM' where PLATFORM is one of these:"
|
||||
@echo " $(PLATS)"
|
||||
@echo "See doc/readme.html for complete instructions."
|
||||
|
||||
guess:
|
||||
@echo Guessing `$(UNAME)`
|
||||
@$(MAKE) `$(UNAME)`
|
||||
|
||||
AIX aix:
|
||||
$(MAKE) $(ALL) CC="xlc" CFLAGS="-O2 -DLUA_USE_POSIX -DLUA_USE_DLOPEN" SYSLIBS="-ldl" SYSLDFLAGS="-brtl -bexpall"
|
||||
|
||||
bsd:
|
||||
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" SYSLIBS="-Wl,-E"
|
||||
|
||||
c89:
|
||||
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_C89" CC="gcc -std=c89"
|
||||
@echo ''
|
||||
@echo '*** C89 does not guarantee 64-bit integers for Lua.'
|
||||
@echo '*** Make sure to compile all external Lua libraries'
|
||||
@echo '*** with LUA_USE_C89 to ensure consistency'
|
||||
@echo ''
|
||||
|
||||
FreeBSD NetBSD OpenBSD freebsd:
|
||||
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX -DLUA_USE_READLINE -I/usr/include/edit" SYSLIBS="-Wl,-E -ledit" CC="cc"
|
||||
|
||||
generic: $(ALL)
|
||||
|
||||
ios:
|
||||
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_IOS"
|
||||
|
||||
Linux linux: linux-noreadline
|
||||
|
||||
linux-noreadline:
|
||||
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX" SYSLIBS="-Wl,-E -ldl"
|
||||
|
||||
linux-readline:
|
||||
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX -DLUA_USE_READLINE" SYSLIBS="-Wl,-E -ldl -lreadline"
|
||||
|
||||
Darwin macos macosx:
|
||||
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_MACOSX -DLUA_USE_READLINE" SYSLIBS="-lreadline"
|
||||
|
||||
mingw:
|
||||
$(MAKE) "LUA_A=lua54.dll" "LUA_T=lua.exe" \
|
||||
"AR=$(CC) -shared -o" "RANLIB=strip --strip-unneeded" \
|
||||
"SYSCFLAGS=-DLUA_BUILD_AS_DLL" "SYSLIBS=" "SYSLDFLAGS=-s" lua.exe
|
||||
$(MAKE) "LUAC_T=luac.exe" luac.exe
|
||||
|
||||
posix:
|
||||
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX"
|
||||
|
||||
SunOS solaris:
|
||||
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN -D_REENTRANT" SYSLIBS="-ldl"
|
||||
|
||||
# Targets that do not create files (not all makes understand .PHONY).
|
||||
.PHONY: all $(PLATS) help test clean default o a depend echo
|
||||
|
||||
# Compiler modules may use special flags.
|
||||
llex.o:
|
||||
$(CC) $(CFLAGS) $(CMCFLAGS) -c llex.c
|
||||
|
||||
lparser.o:
|
||||
$(CC) $(CFLAGS) $(CMCFLAGS) -c lparser.c
|
||||
|
||||
lcode.o:
|
||||
$(CC) $(CFLAGS) $(CMCFLAGS) -c lcode.c
|
||||
|
||||
# DO NOT DELETE
|
||||
|
||||
lapi.o: lapi.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \
|
||||
lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h lstring.h \
|
||||
ltable.h lundump.h lvm.h
|
||||
lauxlib.o: lauxlib.c lprefix.h lua.h luaconf.h lauxlib.h
|
||||
lbaselib.o: lbaselib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
||||
lcode.o: lcode.c lprefix.h lua.h luaconf.h lcode.h llex.h lobject.h \
|
||||
llimits.h lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h \
|
||||
ldo.h lgc.h lstring.h ltable.h lvm.h
|
||||
lcorolib.o: lcorolib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
||||
lctype.o: lctype.c lprefix.h lctype.h lua.h luaconf.h llimits.h
|
||||
ldblib.o: ldblib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
||||
ldebug.o: ldebug.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \
|
||||
lobject.h ltm.h lzio.h lmem.h lcode.h llex.h lopcodes.h lparser.h \
|
||||
ldebug.h ldo.h lfunc.h lstring.h lgc.h ltable.h lvm.h
|
||||
ldo.o: ldo.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \
|
||||
lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h lopcodes.h \
|
||||
lparser.h lstring.h ltable.h lundump.h lvm.h
|
||||
ldump.o: ldump.c lprefix.h lua.h luaconf.h lobject.h llimits.h lstate.h \
|
||||
ltm.h lzio.h lmem.h lundump.h
|
||||
lfunc.o: lfunc.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
|
||||
llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h
|
||||
lgc.o: lgc.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
|
||||
llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lstring.h ltable.h
|
||||
linit.o: linit.c lprefix.h lua.h luaconf.h lualib.h lauxlib.h
|
||||
liolib.o: liolib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
||||
llex.o: llex.c lprefix.h lua.h luaconf.h lctype.h llimits.h ldebug.h \
|
||||
lstate.h lobject.h ltm.h lzio.h lmem.h ldo.h lgc.h llex.h lparser.h \
|
||||
lstring.h ltable.h
|
||||
lmathlib.o: lmathlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
||||
lmem.o: lmem.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
|
||||
llimits.h ltm.h lzio.h lmem.h ldo.h lgc.h
|
||||
loadlib.o: loadlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
||||
lobject.o: lobject.c lprefix.h lua.h luaconf.h lctype.h llimits.h \
|
||||
ldebug.h lstate.h lobject.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h \
|
||||
lvm.h
|
||||
lopcodes.o: lopcodes.c lprefix.h lopcodes.h llimits.h lua.h luaconf.h
|
||||
loslib.o: loslib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
||||
lparser.o: lparser.c lprefix.h lua.h luaconf.h lcode.h llex.h lobject.h \
|
||||
llimits.h lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h \
|
||||
ldo.h lfunc.h lstring.h lgc.h ltable.h
|
||||
lstate.o: lstate.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \
|
||||
lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h llex.h \
|
||||
lstring.h ltable.h
|
||||
lstring.o: lstring.c lprefix.h lua.h luaconf.h ldebug.h lstate.h \
|
||||
lobject.h llimits.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h
|
||||
lstrlib.o: lstrlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
||||
ltable.o: ltable.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
|
||||
llimits.h ltm.h lzio.h lmem.h ldo.h lgc.h lstring.h ltable.h lvm.h
|
||||
ltablib.o: ltablib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
||||
ltm.o: ltm.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
|
||||
llimits.h ltm.h lzio.h lmem.h ldo.h lgc.h lstring.h ltable.h lvm.h
|
||||
lua.o: lua.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
||||
luac.o: luac.c lprefix.h lua.h luaconf.h lauxlib.h ldebug.h lstate.h \
|
||||
lobject.h llimits.h ltm.h lzio.h lmem.h lopcodes.h lopnames.h lundump.h
|
||||
lundump.o: lundump.c lprefix.h lua.h luaconf.h ldebug.h lstate.h \
|
||||
lobject.h llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lstring.h lgc.h \
|
||||
lundump.h
|
||||
lutf8lib.o: lutf8lib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
|
||||
lvm.o: lvm.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
|
||||
llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lopcodes.h lstring.h \
|
||||
ltable.h lvm.h ljumptab.h
|
||||
lzio.o: lzio.c lprefix.h lua.h luaconf.h llimits.h lmem.h lstate.h \
|
||||
lobject.h ltm.h lzio.h
|
||||
|
||||
# (end of Makefile)
|
||||
1463
src/lua/lua-5.4.8/src/lapi.c
Normal file
52
src/lua/lua-5.4.8/src/lapi.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
** $Id: lapi.h $
|
||||
** Auxiliary functions from Lua API
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#ifndef lapi_h
|
||||
#define lapi_h
|
||||
|
||||
|
||||
#include "llimits.h"
|
||||
#include "lstate.h"
|
||||
|
||||
|
||||
/* Increments 'L->top.p', checking for stack overflows */
|
||||
#define api_incr_top(L) {L->top.p++; \
|
||||
api_check(L, L->top.p <= L->ci->top.p, \
|
||||
"stack overflow");}
|
||||
|
||||
|
||||
/*
|
||||
** If a call returns too many multiple returns, the callee may not have
|
||||
** stack space to accommodate all results. In this case, this macro
|
||||
** increases its stack space ('L->ci->top.p').
|
||||
*/
|
||||
#define adjustresults(L,nres) \
|
||||
{ if ((nres) <= LUA_MULTRET && L->ci->top.p < L->top.p) \
|
||||
L->ci->top.p = L->top.p; }
|
||||
|
||||
|
||||
/* Ensure the stack has at least 'n' elements */
|
||||
#define api_checknelems(L,n) \
|
||||
api_check(L, (n) < (L->top.p - L->ci->func.p), \
|
||||
"not enough elements in the stack")
|
||||
|
||||
|
||||
/*
|
||||
** To reduce the overhead of returning from C functions, the presence of
|
||||
** to-be-closed variables in these functions is coded in the CallInfo's
|
||||
** field 'nresults', in a way that functions with no to-be-closed variables
|
||||
** with zero, one, or "all" wanted results have no overhead. Functions
|
||||
** with other number of wanted results, as well as functions with
|
||||
** variables to be closed, have an extra check.
|
||||
*/
|
||||
|
||||
#define hastocloseCfunc(n) ((n) < LUA_MULTRET)
|
||||
|
||||
/* Map [-1, inf) (range of 'nresults') into (-inf, -2] */
|
||||
#define codeNresults(n) (-(n) - 3)
|
||||
#define decodeNresults(n) (-(n) - 3)
|
||||
|
||||
#endif
|
||||
1126
src/lua/lua-5.4.8/src/lauxlib.c
Normal file
301
src/lua/lua-5.4.8/src/lauxlib.h
Normal file
@@ -0,0 +1,301 @@
|
||||
/*
|
||||
** $Id: lauxlib.h $
|
||||
** Auxiliary functions for building Lua libraries
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
|
||||
#ifndef lauxlib_h
|
||||
#define lauxlib_h
|
||||
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "luaconf.h"
|
||||
#include "lua.h"
|
||||
|
||||
|
||||
/* global table */
|
||||
#define LUA_GNAME "_G"
|
||||
|
||||
|
||||
typedef struct luaL_Buffer luaL_Buffer;
|
||||
|
||||
|
||||
/* extra error code for 'luaL_loadfilex' */
|
||||
#define LUA_ERRFILE (LUA_ERRERR+1)
|
||||
|
||||
|
||||
/* key, in the registry, for table of loaded modules */
|
||||
#define LUA_LOADED_TABLE "_LOADED"
|
||||
|
||||
|
||||
/* key, in the registry, for table of preloaded loaders */
|
||||
#define LUA_PRELOAD_TABLE "_PRELOAD"
|
||||
|
||||
|
||||
typedef struct luaL_Reg {
|
||||
const char *name;
|
||||
lua_CFunction func;
|
||||
} luaL_Reg;
|
||||
|
||||
|
||||
#define LUAL_NUMSIZES (sizeof(lua_Integer)*16 + sizeof(lua_Number))
|
||||
|
||||
LUALIB_API void (luaL_checkversion_) (lua_State *L, lua_Number ver, size_t sz);
|
||||
#define luaL_checkversion(L) \
|
||||
luaL_checkversion_(L, LUA_VERSION_NUM, LUAL_NUMSIZES)
|
||||
|
||||
LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e);
|
||||
LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e);
|
||||
LUALIB_API const char *(luaL_tolstring) (lua_State *L, int idx, size_t *len);
|
||||
LUALIB_API int (luaL_argerror) (lua_State *L, int arg, const char *extramsg);
|
||||
LUALIB_API int (luaL_typeerror) (lua_State *L, int arg, const char *tname);
|
||||
LUALIB_API const char *(luaL_checklstring) (lua_State *L, int arg,
|
||||
size_t *l);
|
||||
LUALIB_API const char *(luaL_optlstring) (lua_State *L, int arg,
|
||||
const char *def, size_t *l);
|
||||
LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int arg);
|
||||
LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int arg, lua_Number def);
|
||||
|
||||
LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int arg);
|
||||
LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int arg,
|
||||
lua_Integer def);
|
||||
|
||||
LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg);
|
||||
LUALIB_API void (luaL_checktype) (lua_State *L, int arg, int t);
|
||||
LUALIB_API void (luaL_checkany) (lua_State *L, int arg);
|
||||
|
||||
LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname);
|
||||
LUALIB_API void (luaL_setmetatable) (lua_State *L, const char *tname);
|
||||
LUALIB_API void *(luaL_testudata) (lua_State *L, int ud, const char *tname);
|
||||
LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname);
|
||||
|
||||
LUALIB_API void (luaL_where) (lua_State *L, int lvl);
|
||||
LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...);
|
||||
|
||||
LUALIB_API int (luaL_checkoption) (lua_State *L, int arg, const char *def,
|
||||
const char *const lst[]);
|
||||
|
||||
LUALIB_API int (luaL_fileresult) (lua_State *L, int stat, const char *fname);
|
||||
LUALIB_API int (luaL_execresult) (lua_State *L, int stat);
|
||||
|
||||
|
||||
/* predefined references */
|
||||
#define LUA_NOREF (-2)
|
||||
#define LUA_REFNIL (-1)
|
||||
|
||||
LUALIB_API int (luaL_ref) (lua_State *L, int t);
|
||||
LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref);
|
||||
|
||||
LUALIB_API int (luaL_loadfilex) (lua_State *L, const char *filename,
|
||||
const char *mode);
|
||||
|
||||
#define luaL_loadfile(L,f) luaL_loadfilex(L,f,NULL)
|
||||
|
||||
LUALIB_API int (luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz,
|
||||
const char *name, const char *mode);
|
||||
LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s);
|
||||
|
||||
LUALIB_API lua_State *(luaL_newstate) (void);
|
||||
|
||||
LUALIB_API lua_Integer (luaL_len) (lua_State *L, int idx);
|
||||
|
||||
LUALIB_API void (luaL_addgsub) (luaL_Buffer *b, const char *s,
|
||||
const char *p, const char *r);
|
||||
LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s,
|
||||
const char *p, const char *r);
|
||||
|
||||
LUALIB_API void (luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup);
|
||||
|
||||
LUALIB_API int (luaL_getsubtable) (lua_State *L, int idx, const char *fname);
|
||||
|
||||
LUALIB_API void (luaL_traceback) (lua_State *L, lua_State *L1,
|
||||
const char *msg, int level);
|
||||
|
||||
LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname,
|
||||
lua_CFunction openf, int glb);
|
||||
|
||||
/*
|
||||
** ===============================================================
|
||||
** some useful macros
|
||||
** ===============================================================
|
||||
*/
|
||||
|
||||
|
||||
#define luaL_newlibtable(L,l) \
|
||||
lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1)
|
||||
|
||||
#define luaL_newlib(L,l) \
|
||||
(luaL_checkversion(L), luaL_newlibtable(L,l), luaL_setfuncs(L,l,0))
|
||||
|
||||
#define luaL_argcheck(L, cond,arg,extramsg) \
|
||||
((void)(luai_likely(cond) || luaL_argerror(L, (arg), (extramsg))))
|
||||
|
||||
#define luaL_argexpected(L,cond,arg,tname) \
|
||||
((void)(luai_likely(cond) || luaL_typeerror(L, (arg), (tname))))
|
||||
|
||||
#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL))
|
||||
#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL))
|
||||
|
||||
#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i)))
|
||||
|
||||
#define luaL_dofile(L, fn) \
|
||||
(luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0))
|
||||
|
||||
#define luaL_dostring(L, s) \
|
||||
(luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0))
|
||||
|
||||
#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n)))
|
||||
|
||||
#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n)))
|
||||
|
||||
#define luaL_loadbuffer(L,s,sz,n) luaL_loadbufferx(L,s,sz,n,NULL)
|
||||
|
||||
|
||||
/*
|
||||
** Perform arithmetic operations on lua_Integer values with wrap-around
|
||||
** semantics, as the Lua core does.
|
||||
*/
|
||||
#define luaL_intop(op,v1,v2) \
|
||||
((lua_Integer)((lua_Unsigned)(v1) op (lua_Unsigned)(v2)))
|
||||
|
||||
|
||||
/* push the value used to represent failure/error */
|
||||
#define luaL_pushfail(L) lua_pushnil(L)
|
||||
|
||||
|
||||
/*
|
||||
** Internal assertions for in-house debugging
|
||||
*/
|
||||
#if !defined(lua_assert)
|
||||
|
||||
#if defined LUAI_ASSERT
|
||||
#include <assert.h>
|
||||
#define lua_assert(c) assert(c)
|
||||
#else
|
||||
#define lua_assert(c) ((void)0)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** {======================================================
|
||||
** Generic Buffer manipulation
|
||||
** =======================================================
|
||||
*/
|
||||
|
||||
struct luaL_Buffer {
|
||||
char *b; /* buffer address */
|
||||
size_t size; /* buffer size */
|
||||
size_t n; /* number of characters in buffer */
|
||||
lua_State *L;
|
||||
union {
|
||||
LUAI_MAXALIGN; /* ensure maximum alignment for buffer */
|
||||
char b[LUAL_BUFFERSIZE]; /* initial buffer */
|
||||
} init;
|
||||
};
|
||||
|
||||
|
||||
#define luaL_bufflen(bf) ((bf)->n)
|
||||
#define luaL_buffaddr(bf) ((bf)->b)
|
||||
|
||||
|
||||
#define luaL_addchar(B,c) \
|
||||
((void)((B)->n < (B)->size || luaL_prepbuffsize((B), 1)), \
|
||||
((B)->b[(B)->n++] = (c)))
|
||||
|
||||
#define luaL_addsize(B,s) ((B)->n += (s))
|
||||
|
||||
#define luaL_buffsub(B,s) ((B)->n -= (s))
|
||||
|
||||
LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B);
|
||||
LUALIB_API char *(luaL_prepbuffsize) (luaL_Buffer *B, size_t sz);
|
||||
LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l);
|
||||
LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s);
|
||||
LUALIB_API void (luaL_addvalue) (luaL_Buffer *B);
|
||||
LUALIB_API void (luaL_pushresult) (luaL_Buffer *B);
|
||||
LUALIB_API void (luaL_pushresultsize) (luaL_Buffer *B, size_t sz);
|
||||
LUALIB_API char *(luaL_buffinitsize) (lua_State *L, luaL_Buffer *B, size_t sz);
|
||||
|
||||
#define luaL_prepbuffer(B) luaL_prepbuffsize(B, LUAL_BUFFERSIZE)
|
||||
|
||||
/* }====================================================== */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** {======================================================
|
||||
** File handles for IO library
|
||||
** =======================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
** A file handle is a userdata with metatable 'LUA_FILEHANDLE' and
|
||||
** initial structure 'luaL_Stream' (it may contain other fields
|
||||
** after that initial structure).
|
||||
*/
|
||||
|
||||
#define LUA_FILEHANDLE "FILE*"
|
||||
|
||||
|
||||
typedef struct luaL_Stream {
|
||||
FILE *f; /* stream (NULL for incompletely created streams) */
|
||||
lua_CFunction closef; /* to close stream (NULL for closed streams) */
|
||||
} luaL_Stream;
|
||||
|
||||
/* }====================================================== */
|
||||
|
||||
/*
|
||||
** {==================================================================
|
||||
** "Abstraction Layer" for basic report of messages and errors
|
||||
** ===================================================================
|
||||
*/
|
||||
|
||||
/* print a string */
|
||||
#if !defined(lua_writestring)
|
||||
#define lua_writestring(s,l) fwrite((s), sizeof(char), (l), stdout)
|
||||
#endif
|
||||
|
||||
/* print a newline and flush the output */
|
||||
#if !defined(lua_writeline)
|
||||
#define lua_writeline() (lua_writestring("\n", 1), fflush(stdout))
|
||||
#endif
|
||||
|
||||
/* print an error message */
|
||||
#if !defined(lua_writestringerror)
|
||||
#define lua_writestringerror(s,p) \
|
||||
(fprintf(stderr, (s), (p)), fflush(stderr))
|
||||
#endif
|
||||
|
||||
/* }================================================================== */
|
||||
|
||||
|
||||
/*
|
||||
** {============================================================
|
||||
** Compatibility with deprecated conversions
|
||||
** =============================================================
|
||||
*/
|
||||
#if defined(LUA_COMPAT_APIINTCASTS)
|
||||
|
||||
#define luaL_checkunsigned(L,a) ((lua_Unsigned)luaL_checkinteger(L,a))
|
||||
#define luaL_optunsigned(L,a,d) \
|
||||
((lua_Unsigned)luaL_optinteger(L,a,(lua_Integer)(d)))
|
||||
|
||||
#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n)))
|
||||
#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d)))
|
||||
|
||||
#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n)))
|
||||
#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d)))
|
||||
|
||||
#endif
|
||||
/* }============================================================ */
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
549
src/lua/lua-5.4.8/src/lbaselib.c
Normal file
@@ -0,0 +1,549 @@
|
||||
/*
|
||||
** $Id: lbaselib.c $
|
||||
** Basic library
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#define lbaselib_c
|
||||
#define LUA_LIB
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lauxlib.h"
|
||||
#include "lualib.h"
|
||||
|
||||
|
||||
static int luaB_print (lua_State *L) {
|
||||
int n = lua_gettop(L); /* number of arguments */
|
||||
int i;
|
||||
for (i = 1; i <= n; i++) { /* for each argument */
|
||||
size_t l;
|
||||
const char *s = luaL_tolstring(L, i, &l); /* convert it to string */
|
||||
if (i > 1) /* not the first element? */
|
||||
lua_writestring("\t", 1); /* add a tab before it */
|
||||
lua_writestring(s, l); /* print it */
|
||||
lua_pop(L, 1); /* pop result */
|
||||
}
|
||||
lua_writeline();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Creates a warning with all given arguments.
|
||||
** Check first for errors; otherwise an error may interrupt
|
||||
** the composition of a warning, leaving it unfinished.
|
||||
*/
|
||||
static int luaB_warn (lua_State *L) {
|
||||
int n = lua_gettop(L); /* number of arguments */
|
||||
int i;
|
||||
luaL_checkstring(L, 1); /* at least one argument */
|
||||
for (i = 2; i <= n; i++)
|
||||
luaL_checkstring(L, i); /* make sure all arguments are strings */
|
||||
for (i = 1; i < n; i++) /* compose warning */
|
||||
lua_warning(L, lua_tostring(L, i), 1);
|
||||
lua_warning(L, lua_tostring(L, n), 0); /* close warning */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#define SPACECHARS " \f\n\r\t\v"
|
||||
|
||||
static const char *b_str2int (const char *s, int base, lua_Integer *pn) {
|
||||
lua_Unsigned n = 0;
|
||||
int neg = 0;
|
||||
s += strspn(s, SPACECHARS); /* skip initial spaces */
|
||||
if (*s == '-') { s++; neg = 1; } /* handle sign */
|
||||
else if (*s == '+') s++;
|
||||
if (!isalnum((unsigned char)*s)) /* no digit? */
|
||||
return NULL;
|
||||
do {
|
||||
int digit = (isdigit((unsigned char)*s)) ? *s - '0'
|
||||
: (toupper((unsigned char)*s) - 'A') + 10;
|
||||
if (digit >= base) return NULL; /* invalid numeral */
|
||||
n = n * base + digit;
|
||||
s++;
|
||||
} while (isalnum((unsigned char)*s));
|
||||
s += strspn(s, SPACECHARS); /* skip trailing spaces */
|
||||
*pn = (lua_Integer)((neg) ? (0u - n) : n);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_tonumber (lua_State *L) {
|
||||
if (lua_isnoneornil(L, 2)) { /* standard conversion? */
|
||||
if (lua_type(L, 1) == LUA_TNUMBER) { /* already a number? */
|
||||
lua_settop(L, 1); /* yes; return it */
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
size_t l;
|
||||
const char *s = lua_tolstring(L, 1, &l);
|
||||
if (s != NULL && lua_stringtonumber(L, s) == l + 1)
|
||||
return 1; /* successful conversion to number */
|
||||
/* else not a number */
|
||||
luaL_checkany(L, 1); /* (but there must be some parameter) */
|
||||
}
|
||||
}
|
||||
else {
|
||||
size_t l;
|
||||
const char *s;
|
||||
lua_Integer n = 0; /* to avoid warnings */
|
||||
lua_Integer base = luaL_checkinteger(L, 2);
|
||||
luaL_checktype(L, 1, LUA_TSTRING); /* no numbers as strings */
|
||||
s = lua_tolstring(L, 1, &l);
|
||||
luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range");
|
||||
if (b_str2int(s, (int)base, &n) == s + l) {
|
||||
lua_pushinteger(L, n);
|
||||
return 1;
|
||||
} /* else not a number */
|
||||
} /* else not a number */
|
||||
luaL_pushfail(L); /* not a number */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_error (lua_State *L) {
|
||||
int level = (int)luaL_optinteger(L, 2, 1);
|
||||
lua_settop(L, 1);
|
||||
if (lua_type(L, 1) == LUA_TSTRING && level > 0) {
|
||||
luaL_where(L, level); /* add extra information */
|
||||
lua_pushvalue(L, 1);
|
||||
lua_concat(L, 2);
|
||||
}
|
||||
return lua_error(L);
|
||||
}
|
||||
|
||||
|
||||
static int luaB_getmetatable (lua_State *L) {
|
||||
luaL_checkany(L, 1);
|
||||
if (!lua_getmetatable(L, 1)) {
|
||||
lua_pushnil(L);
|
||||
return 1; /* no metatable */
|
||||
}
|
||||
luaL_getmetafield(L, 1, "__metatable");
|
||||
return 1; /* returns either __metatable field (if present) or metatable */
|
||||
}
|
||||
|
||||
|
||||
static int luaB_setmetatable (lua_State *L) {
|
||||
int t = lua_type(L, 2);
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
luaL_argexpected(L, t == LUA_TNIL || t == LUA_TTABLE, 2, "nil or table");
|
||||
if (l_unlikely(luaL_getmetafield(L, 1, "__metatable") != LUA_TNIL))
|
||||
return luaL_error(L, "cannot change a protected metatable");
|
||||
lua_settop(L, 2);
|
||||
lua_setmetatable(L, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_rawequal (lua_State *L) {
|
||||
luaL_checkany(L, 1);
|
||||
luaL_checkany(L, 2);
|
||||
lua_pushboolean(L, lua_rawequal(L, 1, 2));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_rawlen (lua_State *L) {
|
||||
int t = lua_type(L, 1);
|
||||
luaL_argexpected(L, t == LUA_TTABLE || t == LUA_TSTRING, 1,
|
||||
"table or string");
|
||||
lua_pushinteger(L, lua_rawlen(L, 1));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_rawget (lua_State *L) {
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
luaL_checkany(L, 2);
|
||||
lua_settop(L, 2);
|
||||
lua_rawget(L, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int luaB_rawset (lua_State *L) {
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
luaL_checkany(L, 2);
|
||||
luaL_checkany(L, 3);
|
||||
lua_settop(L, 3);
|
||||
lua_rawset(L, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int pushmode (lua_State *L, int oldmode) {
|
||||
if (oldmode == -1)
|
||||
luaL_pushfail(L); /* invalid call to 'lua_gc' */
|
||||
else
|
||||
lua_pushstring(L, (oldmode == LUA_GCINC) ? "incremental"
|
||||
: "generational");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** check whether call to 'lua_gc' was valid (not inside a finalizer)
|
||||
*/
|
||||
#define checkvalres(res) { if (res == -1) break; }
|
||||
|
||||
static int luaB_collectgarbage (lua_State *L) {
|
||||
static const char *const opts[] = {"stop", "restart", "collect",
|
||||
"count", "step", "setpause", "setstepmul",
|
||||
"isrunning", "generational", "incremental", NULL};
|
||||
static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT,
|
||||
LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL,
|
||||
LUA_GCISRUNNING, LUA_GCGEN, LUA_GCINC};
|
||||
int o = optsnum[luaL_checkoption(L, 1, "collect", opts)];
|
||||
switch (o) {
|
||||
case LUA_GCCOUNT: {
|
||||
int k = lua_gc(L, o);
|
||||
int b = lua_gc(L, LUA_GCCOUNTB);
|
||||
checkvalres(k);
|
||||
lua_pushnumber(L, (lua_Number)k + ((lua_Number)b/1024));
|
||||
return 1;
|
||||
}
|
||||
case LUA_GCSTEP: {
|
||||
int step = (int)luaL_optinteger(L, 2, 0);
|
||||
int res = lua_gc(L, o, step);
|
||||
checkvalres(res);
|
||||
lua_pushboolean(L, res);
|
||||
return 1;
|
||||
}
|
||||
case LUA_GCSETPAUSE:
|
||||
case LUA_GCSETSTEPMUL: {
|
||||
int p = (int)luaL_optinteger(L, 2, 0);
|
||||
int previous = lua_gc(L, o, p);
|
||||
checkvalres(previous);
|
||||
lua_pushinteger(L, previous);
|
||||
return 1;
|
||||
}
|
||||
case LUA_GCISRUNNING: {
|
||||
int res = lua_gc(L, o);
|
||||
checkvalres(res);
|
||||
lua_pushboolean(L, res);
|
||||
return 1;
|
||||
}
|
||||
case LUA_GCGEN: {
|
||||
int minormul = (int)luaL_optinteger(L, 2, 0);
|
||||
int majormul = (int)luaL_optinteger(L, 3, 0);
|
||||
return pushmode(L, lua_gc(L, o, minormul, majormul));
|
||||
}
|
||||
case LUA_GCINC: {
|
||||
int pause = (int)luaL_optinteger(L, 2, 0);
|
||||
int stepmul = (int)luaL_optinteger(L, 3, 0);
|
||||
int stepsize = (int)luaL_optinteger(L, 4, 0);
|
||||
return pushmode(L, lua_gc(L, o, pause, stepmul, stepsize));
|
||||
}
|
||||
default: {
|
||||
int res = lua_gc(L, o);
|
||||
checkvalres(res);
|
||||
lua_pushinteger(L, res);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
luaL_pushfail(L); /* invalid call (inside a finalizer) */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_type (lua_State *L) {
|
||||
int t = lua_type(L, 1);
|
||||
luaL_argcheck(L, t != LUA_TNONE, 1, "value expected");
|
||||
lua_pushstring(L, lua_typename(L, t));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_next (lua_State *L) {
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
lua_settop(L, 2); /* create a 2nd argument if there isn't one */
|
||||
if (lua_next(L, 1))
|
||||
return 2;
|
||||
else {
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int pairscont (lua_State *L, int status, lua_KContext k) {
|
||||
(void)L; (void)status; (void)k; /* unused */
|
||||
return 3;
|
||||
}
|
||||
|
||||
static int luaB_pairs (lua_State *L) {
|
||||
luaL_checkany(L, 1);
|
||||
if (luaL_getmetafield(L, 1, "__pairs") == LUA_TNIL) { /* no metamethod? */
|
||||
lua_pushcfunction(L, luaB_next); /* will return generator, */
|
||||
lua_pushvalue(L, 1); /* state, */
|
||||
lua_pushnil(L); /* and initial value */
|
||||
}
|
||||
else {
|
||||
lua_pushvalue(L, 1); /* argument 'self' to metamethod */
|
||||
lua_callk(L, 1, 3, 0, pairscont); /* get 3 values from metamethod */
|
||||
}
|
||||
return 3;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Traversal function for 'ipairs'
|
||||
*/
|
||||
static int ipairsaux (lua_State *L) {
|
||||
lua_Integer i = luaL_checkinteger(L, 2);
|
||||
i = luaL_intop(+, i, 1);
|
||||
lua_pushinteger(L, i);
|
||||
return (lua_geti(L, 1, i) == LUA_TNIL) ? 1 : 2;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** 'ipairs' function. Returns 'ipairsaux', given "table", 0.
|
||||
** (The given "table" may not be a table.)
|
||||
*/
|
||||
static int luaB_ipairs (lua_State *L) {
|
||||
luaL_checkany(L, 1);
|
||||
lua_pushcfunction(L, ipairsaux); /* iteration function */
|
||||
lua_pushvalue(L, 1); /* state */
|
||||
lua_pushinteger(L, 0); /* initial value */
|
||||
return 3;
|
||||
}
|
||||
|
||||
|
||||
static int load_aux (lua_State *L, int status, int envidx) {
|
||||
if (l_likely(status == LUA_OK)) {
|
||||
if (envidx != 0) { /* 'env' parameter? */
|
||||
lua_pushvalue(L, envidx); /* environment for loaded function */
|
||||
if (!lua_setupvalue(L, -2, 1)) /* set it as 1st upvalue */
|
||||
lua_pop(L, 1); /* remove 'env' if not used by previous call */
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
else { /* error (message is on top of the stack) */
|
||||
luaL_pushfail(L);
|
||||
lua_insert(L, -2); /* put before error message */
|
||||
return 2; /* return fail plus error message */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int luaB_loadfile (lua_State *L) {
|
||||
const char *fname = luaL_optstring(L, 1, NULL);
|
||||
const char *mode = luaL_optstring(L, 2, NULL);
|
||||
int env = (!lua_isnone(L, 3) ? 3 : 0); /* 'env' index or 0 if no 'env' */
|
||||
int status = luaL_loadfilex(L, fname, mode);
|
||||
return load_aux(L, status, env);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** {======================================================
|
||||
** Generic Read function
|
||||
** =======================================================
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
** reserved slot, above all arguments, to hold a copy of the returned
|
||||
** string to avoid it being collected while parsed. 'load' has four
|
||||
** optional arguments (chunk, source name, mode, and environment).
|
||||
*/
|
||||
#define RESERVEDSLOT 5
|
||||
|
||||
|
||||
/*
|
||||
** Reader for generic 'load' function: 'lua_load' uses the
|
||||
** stack for internal stuff, so the reader cannot change the
|
||||
** stack top. Instead, it keeps its resulting string in a
|
||||
** reserved slot inside the stack.
|
||||
*/
|
||||
static const char *generic_reader (lua_State *L, void *ud, size_t *size) {
|
||||
(void)(ud); /* not used */
|
||||
luaL_checkstack(L, 2, "too many nested functions");
|
||||
lua_pushvalue(L, 1); /* get function */
|
||||
lua_call(L, 0, 1); /* call it */
|
||||
if (lua_isnil(L, -1)) {
|
||||
lua_pop(L, 1); /* pop result */
|
||||
*size = 0;
|
||||
return NULL;
|
||||
}
|
||||
else if (l_unlikely(!lua_isstring(L, -1)))
|
||||
luaL_error(L, "reader function must return a string");
|
||||
lua_replace(L, RESERVEDSLOT); /* save string in reserved slot */
|
||||
return lua_tolstring(L, RESERVEDSLOT, size);
|
||||
}
|
||||
|
||||
|
||||
static int luaB_load (lua_State *L) {
|
||||
int status;
|
||||
size_t l;
|
||||
const char *s = lua_tolstring(L, 1, &l);
|
||||
const char *mode = luaL_optstring(L, 3, "bt");
|
||||
int env = (!lua_isnone(L, 4) ? 4 : 0); /* 'env' index or 0 if no 'env' */
|
||||
if (s != NULL) { /* loading a string? */
|
||||
const char *chunkname = luaL_optstring(L, 2, s);
|
||||
status = luaL_loadbufferx(L, s, l, chunkname, mode);
|
||||
}
|
||||
else { /* loading from a reader function */
|
||||
const char *chunkname = luaL_optstring(L, 2, "=(load)");
|
||||
luaL_checktype(L, 1, LUA_TFUNCTION);
|
||||
lua_settop(L, RESERVEDSLOT); /* create reserved slot */
|
||||
status = lua_load(L, generic_reader, NULL, chunkname, mode);
|
||||
}
|
||||
return load_aux(L, status, env);
|
||||
}
|
||||
|
||||
/* }====================================================== */
|
||||
|
||||
|
||||
static int dofilecont (lua_State *L, int d1, lua_KContext d2) {
|
||||
(void)d1; (void)d2; /* only to match 'lua_Kfunction' prototype */
|
||||
return lua_gettop(L) - 1;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_dofile (lua_State *L) {
|
||||
const char *fname = luaL_optstring(L, 1, NULL);
|
||||
lua_settop(L, 1);
|
||||
if (l_unlikely(luaL_loadfile(L, fname) != LUA_OK))
|
||||
return lua_error(L);
|
||||
lua_callk(L, 0, LUA_MULTRET, 0, dofilecont);
|
||||
return dofilecont(L, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
static int luaB_assert (lua_State *L) {
|
||||
if (l_likely(lua_toboolean(L, 1))) /* condition is true? */
|
||||
return lua_gettop(L); /* return all arguments */
|
||||
else { /* error */
|
||||
luaL_checkany(L, 1); /* there must be a condition */
|
||||
lua_remove(L, 1); /* remove it */
|
||||
lua_pushliteral(L, "assertion failed!"); /* default message */
|
||||
lua_settop(L, 1); /* leave only message (default if no other one) */
|
||||
return luaB_error(L); /* call 'error' */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int luaB_select (lua_State *L) {
|
||||
int n = lua_gettop(L);
|
||||
if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') {
|
||||
lua_pushinteger(L, n-1);
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
lua_Integer i = luaL_checkinteger(L, 1);
|
||||
if (i < 0) i = n + i;
|
||||
else if (i > n) i = n;
|
||||
luaL_argcheck(L, 1 <= i, 1, "index out of range");
|
||||
return n - (int)i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Continuation function for 'pcall' and 'xpcall'. Both functions
|
||||
** already pushed a 'true' before doing the call, so in case of success
|
||||
** 'finishpcall' only has to return everything in the stack minus
|
||||
** 'extra' values (where 'extra' is exactly the number of items to be
|
||||
** ignored).
|
||||
*/
|
||||
static int finishpcall (lua_State *L, int status, lua_KContext extra) {
|
||||
if (l_unlikely(status != LUA_OK && status != LUA_YIELD)) { /* error? */
|
||||
lua_pushboolean(L, 0); /* first result (false) */
|
||||
lua_pushvalue(L, -2); /* error message */
|
||||
return 2; /* return false, msg */
|
||||
}
|
||||
else
|
||||
return lua_gettop(L) - (int)extra; /* return all results */
|
||||
}
|
||||
|
||||
|
||||
static int luaB_pcall (lua_State *L) {
|
||||
int status;
|
||||
luaL_checkany(L, 1);
|
||||
lua_pushboolean(L, 1); /* first result if no errors */
|
||||
lua_insert(L, 1); /* put it in place */
|
||||
status = lua_pcallk(L, lua_gettop(L) - 2, LUA_MULTRET, 0, 0, finishpcall);
|
||||
return finishpcall(L, status, 0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Do a protected call with error handling. After 'lua_rotate', the
|
||||
** stack will have <f, err, true, f, [args...]>; so, the function passes
|
||||
** 2 to 'finishpcall' to skip the 2 first values when returning results.
|
||||
*/
|
||||
static int luaB_xpcall (lua_State *L) {
|
||||
int status;
|
||||
int n = lua_gettop(L);
|
||||
luaL_checktype(L, 2, LUA_TFUNCTION); /* check error function */
|
||||
lua_pushboolean(L, 1); /* first result */
|
||||
lua_pushvalue(L, 1); /* function */
|
||||
lua_rotate(L, 3, 2); /* move them below function's arguments */
|
||||
status = lua_pcallk(L, n - 2, LUA_MULTRET, 2, 2, finishpcall);
|
||||
return finishpcall(L, status, 2);
|
||||
}
|
||||
|
||||
|
||||
static int luaB_tostring (lua_State *L) {
|
||||
luaL_checkany(L, 1);
|
||||
luaL_tolstring(L, 1, NULL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static const luaL_Reg base_funcs[] = {
|
||||
{"assert", luaB_assert},
|
||||
{"collectgarbage", luaB_collectgarbage},
|
||||
{"dofile", luaB_dofile},
|
||||
{"error", luaB_error},
|
||||
{"getmetatable", luaB_getmetatable},
|
||||
{"ipairs", luaB_ipairs},
|
||||
{"loadfile", luaB_loadfile},
|
||||
{"load", luaB_load},
|
||||
{"next", luaB_next},
|
||||
{"pairs", luaB_pairs},
|
||||
{"pcall", luaB_pcall},
|
||||
{"print", luaB_print},
|
||||
{"warn", luaB_warn},
|
||||
{"rawequal", luaB_rawequal},
|
||||
{"rawlen", luaB_rawlen},
|
||||
{"rawget", luaB_rawget},
|
||||
{"rawset", luaB_rawset},
|
||||
{"select", luaB_select},
|
||||
{"setmetatable", luaB_setmetatable},
|
||||
{"tonumber", luaB_tonumber},
|
||||
{"tostring", luaB_tostring},
|
||||
{"type", luaB_type},
|
||||
{"xpcall", luaB_xpcall},
|
||||
/* placeholders */
|
||||
{LUA_GNAME, NULL},
|
||||
{"_VERSION", NULL},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
LUAMOD_API int luaopen_base (lua_State *L) {
|
||||
/* open lib into global table */
|
||||
lua_pushglobaltable(L);
|
||||
luaL_setfuncs(L, base_funcs, 0);
|
||||
/* set global _G */
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setfield(L, -2, LUA_GNAME);
|
||||
/* set global _VERSION */
|
||||
lua_pushliteral(L, LUA_VERSION);
|
||||
lua_setfield(L, -2, "_VERSION");
|
||||
return 1;
|
||||
}
|
||||
|
||||
1875
src/lua/lua-5.4.8/src/lcode.c
Normal file
101
src/lua/lua-5.4.8/src/lcode.h
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
** $Id: lcode.h $
|
||||
** Code generator for Lua
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#ifndef lcode_h
|
||||
#define lcode_h
|
||||
|
||||
#include "llex.h"
|
||||
#include "lobject.h"
|
||||
#include "lopcodes.h"
|
||||
#include "lparser.h"
|
||||
|
||||
|
||||
/*
|
||||
** Marks the end of a patch list. It is an invalid value both as an absolute
|
||||
** address, and as a list link (would link an element to itself).
|
||||
*/
|
||||
#define NO_JUMP (-1)
|
||||
|
||||
|
||||
/*
|
||||
** grep "ORDER OPR" if you change these enums (ORDER OP)
|
||||
*/
|
||||
typedef enum BinOpr {
|
||||
/* arithmetic operators */
|
||||
OPR_ADD, OPR_SUB, OPR_MUL, OPR_MOD, OPR_POW,
|
||||
OPR_DIV, OPR_IDIV,
|
||||
/* bitwise operators */
|
||||
OPR_BAND, OPR_BOR, OPR_BXOR,
|
||||
OPR_SHL, OPR_SHR,
|
||||
/* string operator */
|
||||
OPR_CONCAT,
|
||||
/* comparison operators */
|
||||
OPR_EQ, OPR_LT, OPR_LE,
|
||||
OPR_NE, OPR_GT, OPR_GE,
|
||||
/* logical operators */
|
||||
OPR_AND, OPR_OR,
|
||||
OPR_NOBINOPR
|
||||
} BinOpr;
|
||||
|
||||
|
||||
/* true if operation is foldable (that is, it is arithmetic or bitwise) */
|
||||
#define foldbinop(op) ((op) <= OPR_SHR)
|
||||
|
||||
|
||||
#define luaK_codeABC(fs,o,a,b,c) luaK_codeABCk(fs,o,a,b,c,0)
|
||||
|
||||
|
||||
typedef enum UnOpr { OPR_MINUS, OPR_BNOT, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr;
|
||||
|
||||
|
||||
/* get (pointer to) instruction of given 'expdesc' */
|
||||
#define getinstruction(fs,e) ((fs)->f->code[(e)->u.info])
|
||||
|
||||
|
||||
#define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET)
|
||||
|
||||
#define luaK_jumpto(fs,t) luaK_patchlist(fs, luaK_jump(fs), t)
|
||||
|
||||
LUAI_FUNC int luaK_code (FuncState *fs, Instruction i);
|
||||
LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx);
|
||||
LUAI_FUNC int luaK_codeABCk (FuncState *fs, OpCode o, int A,
|
||||
int B, int C, int k);
|
||||
LUAI_FUNC int luaK_exp2const (FuncState *fs, const expdesc *e, TValue *v);
|
||||
LUAI_FUNC void luaK_fixline (FuncState *fs, int line);
|
||||
LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n);
|
||||
LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n);
|
||||
LUAI_FUNC void luaK_checkstack (FuncState *fs, int n);
|
||||
LUAI_FUNC void luaK_int (FuncState *fs, int reg, lua_Integer n);
|
||||
LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e);
|
||||
LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e);
|
||||
LUAI_FUNC void luaK_exp2anyregup (FuncState *fs, expdesc *e);
|
||||
LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e);
|
||||
LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e);
|
||||
LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key);
|
||||
LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k);
|
||||
LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e);
|
||||
LUAI_FUNC void luaK_goiffalse (FuncState *fs, expdesc *e);
|
||||
LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e);
|
||||
LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults);
|
||||
LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e);
|
||||
LUAI_FUNC int luaK_jump (FuncState *fs);
|
||||
LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret);
|
||||
LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target);
|
||||
LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list);
|
||||
LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2);
|
||||
LUAI_FUNC int luaK_getlabel (FuncState *fs);
|
||||
LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v, int line);
|
||||
LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v);
|
||||
LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1,
|
||||
expdesc *v2, int line);
|
||||
LUAI_FUNC void luaK_settablesize (FuncState *fs, int pc,
|
||||
int ra, int asize, int hsize);
|
||||
LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore);
|
||||
LUAI_FUNC void luaK_finish (FuncState *fs);
|
||||
LUAI_FUNC l_noret luaK_semerror (LexState *ls, const char *msg);
|
||||
|
||||
|
||||
#endif
|
||||
210
src/lua/lua-5.4.8/src/lcorolib.c
Normal file
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
** $Id: lcorolib.c $
|
||||
** Coroutine Library
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#define lcorolib_c
|
||||
#define LUA_LIB
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lauxlib.h"
|
||||
#include "lualib.h"
|
||||
|
||||
|
||||
static lua_State *getco (lua_State *L) {
|
||||
lua_State *co = lua_tothread(L, 1);
|
||||
luaL_argexpected(L, co, 1, "thread");
|
||||
return co;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Resumes a coroutine. Returns the number of results for non-error
|
||||
** cases or -1 for errors.
|
||||
*/
|
||||
static int auxresume (lua_State *L, lua_State *co, int narg) {
|
||||
int status, nres;
|
||||
if (l_unlikely(!lua_checkstack(co, narg))) {
|
||||
lua_pushliteral(L, "too many arguments to resume");
|
||||
return -1; /* error flag */
|
||||
}
|
||||
lua_xmove(L, co, narg);
|
||||
status = lua_resume(co, L, narg, &nres);
|
||||
if (l_likely(status == LUA_OK || status == LUA_YIELD)) {
|
||||
if (l_unlikely(!lua_checkstack(L, nres + 1))) {
|
||||
lua_pop(co, nres); /* remove results anyway */
|
||||
lua_pushliteral(L, "too many results to resume");
|
||||
return -1; /* error flag */
|
||||
}
|
||||
lua_xmove(co, L, nres); /* move yielded values */
|
||||
return nres;
|
||||
}
|
||||
else {
|
||||
lua_xmove(co, L, 1); /* move error message */
|
||||
return -1; /* error flag */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int luaB_coresume (lua_State *L) {
|
||||
lua_State *co = getco(L);
|
||||
int r;
|
||||
r = auxresume(L, co, lua_gettop(L) - 1);
|
||||
if (l_unlikely(r < 0)) {
|
||||
lua_pushboolean(L, 0);
|
||||
lua_insert(L, -2);
|
||||
return 2; /* return false + error message */
|
||||
}
|
||||
else {
|
||||
lua_pushboolean(L, 1);
|
||||
lua_insert(L, -(r + 1));
|
||||
return r + 1; /* return true + 'resume' returns */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int luaB_auxwrap (lua_State *L) {
|
||||
lua_State *co = lua_tothread(L, lua_upvalueindex(1));
|
||||
int r = auxresume(L, co, lua_gettop(L));
|
||||
if (l_unlikely(r < 0)) { /* error? */
|
||||
int stat = lua_status(co);
|
||||
if (stat != LUA_OK && stat != LUA_YIELD) { /* error in the coroutine? */
|
||||
stat = lua_closethread(co, L); /* close its tbc variables */
|
||||
lua_assert(stat != LUA_OK);
|
||||
lua_xmove(co, L, 1); /* move error message to the caller */
|
||||
}
|
||||
if (stat != LUA_ERRMEM && /* not a memory error and ... */
|
||||
lua_type(L, -1) == LUA_TSTRING) { /* ... error object is a string? */
|
||||
luaL_where(L, 1); /* add extra info, if available */
|
||||
lua_insert(L, -2);
|
||||
lua_concat(L, 2);
|
||||
}
|
||||
return lua_error(L); /* propagate error */
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_cocreate (lua_State *L) {
|
||||
lua_State *NL;
|
||||
luaL_checktype(L, 1, LUA_TFUNCTION);
|
||||
NL = lua_newthread(L);
|
||||
lua_pushvalue(L, 1); /* move function to top */
|
||||
lua_xmove(L, NL, 1); /* move function from L to NL */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_cowrap (lua_State *L) {
|
||||
luaB_cocreate(L);
|
||||
lua_pushcclosure(L, luaB_auxwrap, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_yield (lua_State *L) {
|
||||
return lua_yield(L, lua_gettop(L));
|
||||
}
|
||||
|
||||
|
||||
#define COS_RUN 0
|
||||
#define COS_DEAD 1
|
||||
#define COS_YIELD 2
|
||||
#define COS_NORM 3
|
||||
|
||||
|
||||
static const char *const statname[] =
|
||||
{"running", "dead", "suspended", "normal"};
|
||||
|
||||
|
||||
static int auxstatus (lua_State *L, lua_State *co) {
|
||||
if (L == co) return COS_RUN;
|
||||
else {
|
||||
switch (lua_status(co)) {
|
||||
case LUA_YIELD:
|
||||
return COS_YIELD;
|
||||
case LUA_OK: {
|
||||
lua_Debug ar;
|
||||
if (lua_getstack(co, 0, &ar)) /* does it have frames? */
|
||||
return COS_NORM; /* it is running */
|
||||
else if (lua_gettop(co) == 0)
|
||||
return COS_DEAD;
|
||||
else
|
||||
return COS_YIELD; /* initial state */
|
||||
}
|
||||
default: /* some error occurred */
|
||||
return COS_DEAD;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int luaB_costatus (lua_State *L) {
|
||||
lua_State *co = getco(L);
|
||||
lua_pushstring(L, statname[auxstatus(L, co)]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_yieldable (lua_State *L) {
|
||||
lua_State *co = lua_isnone(L, 1) ? L : getco(L);
|
||||
lua_pushboolean(L, lua_isyieldable(co));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_corunning (lua_State *L) {
|
||||
int ismain = lua_pushthread(L);
|
||||
lua_pushboolean(L, ismain);
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_close (lua_State *L) {
|
||||
lua_State *co = getco(L);
|
||||
int status = auxstatus(L, co);
|
||||
switch (status) {
|
||||
case COS_DEAD: case COS_YIELD: {
|
||||
status = lua_closethread(co, L);
|
||||
if (status == LUA_OK) {
|
||||
lua_pushboolean(L, 1);
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
lua_pushboolean(L, 0);
|
||||
lua_xmove(co, L, 1); /* move error message */
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
default: /* normal or running coroutine */
|
||||
return luaL_error(L, "cannot close a %s coroutine", statname[status]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static const luaL_Reg co_funcs[] = {
|
||||
{"create", luaB_cocreate},
|
||||
{"resume", luaB_coresume},
|
||||
{"running", luaB_corunning},
|
||||
{"status", luaB_costatus},
|
||||
{"wrap", luaB_cowrap},
|
||||
{"yield", luaB_yield},
|
||||
{"isyieldable", luaB_yieldable},
|
||||
{"close", luaB_close},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
|
||||
LUAMOD_API int luaopen_coroutine (lua_State *L) {
|
||||
luaL_newlib(L, co_funcs);
|
||||
return 1;
|
||||
}
|
||||
|
||||
64
src/lua/lua-5.4.8/src/lctype.c
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
** $Id: lctype.c $
|
||||
** 'ctype' functions for Lua
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#define lctype_c
|
||||
#define LUA_CORE
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
|
||||
#include "lctype.h"
|
||||
|
||||
#if !LUA_USE_CTYPE /* { */
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
|
||||
#if defined (LUA_UCID) /* accept UniCode IDentifiers? */
|
||||
/* consider all non-ascii codepoints to be alphabetic */
|
||||
#define NONA 0x01
|
||||
#else
|
||||
#define NONA 0x00 /* default */
|
||||
#endif
|
||||
|
||||
|
||||
LUAI_DDEF const lu_byte luai_ctype_[UCHAR_MAX + 2] = {
|
||||
0x00, /* EOZ */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0. */
|
||||
0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1. */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x0c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, /* 2. */
|
||||
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
|
||||
0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, /* 3. */
|
||||
0x16, 0x16, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
|
||||
0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 4. */
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 5. */
|
||||
0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x05,
|
||||
0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 6. */
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 7. */
|
||||
0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x00,
|
||||
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, /* 8. */
|
||||
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA,
|
||||
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, /* 9. */
|
||||
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA,
|
||||
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, /* a. */
|
||||
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA,
|
||||
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, /* b. */
|
||||
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA,
|
||||
0x00, 0x00, NONA, NONA, NONA, NONA, NONA, NONA, /* c. */
|
||||
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA,
|
||||
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, /* d. */
|
||||
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA,
|
||||
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, /* e. */
|
||||
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA,
|
||||
NONA, NONA, NONA, NONA, NONA, 0x00, 0x00, 0x00, /* f. */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
#endif /* } */
|
||||
101
src/lua/lua-5.4.8/src/lctype.h
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
** $Id: lctype.h $
|
||||
** 'ctype' functions for Lua
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#ifndef lctype_h
|
||||
#define lctype_h
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
|
||||
/*
|
||||
** WARNING: the functions defined here do not necessarily correspond
|
||||
** to the similar functions in the standard C ctype.h. They are
|
||||
** optimized for the specific needs of Lua.
|
||||
*/
|
||||
|
||||
#if !defined(LUA_USE_CTYPE)
|
||||
|
||||
#if 'A' == 65 && '0' == 48
|
||||
/* ASCII case: can use its own tables; faster and fixed */
|
||||
#define LUA_USE_CTYPE 0
|
||||
#else
|
||||
/* must use standard C ctype */
|
||||
#define LUA_USE_CTYPE 1
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if !LUA_USE_CTYPE /* { */
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include "llimits.h"
|
||||
|
||||
|
||||
#define ALPHABIT 0
|
||||
#define DIGITBIT 1
|
||||
#define PRINTBIT 2
|
||||
#define SPACEBIT 3
|
||||
#define XDIGITBIT 4
|
||||
|
||||
|
||||
#define MASK(B) (1 << (B))
|
||||
|
||||
|
||||
/*
|
||||
** add 1 to char to allow index -1 (EOZ)
|
||||
*/
|
||||
#define testprop(c,p) (luai_ctype_[(c)+1] & (p))
|
||||
|
||||
/*
|
||||
** 'lalpha' (Lua alphabetic) and 'lalnum' (Lua alphanumeric) both include '_'
|
||||
*/
|
||||
#define lislalpha(c) testprop(c, MASK(ALPHABIT))
|
||||
#define lislalnum(c) testprop(c, (MASK(ALPHABIT) | MASK(DIGITBIT)))
|
||||
#define lisdigit(c) testprop(c, MASK(DIGITBIT))
|
||||
#define lisspace(c) testprop(c, MASK(SPACEBIT))
|
||||
#define lisprint(c) testprop(c, MASK(PRINTBIT))
|
||||
#define lisxdigit(c) testprop(c, MASK(XDIGITBIT))
|
||||
|
||||
|
||||
/*
|
||||
** In ASCII, this 'ltolower' is correct for alphabetic characters and
|
||||
** for '.'. That is enough for Lua needs. ('check_exp' ensures that
|
||||
** the character either is an upper-case letter or is unchanged by
|
||||
** the transformation, which holds for lower-case letters and '.'.)
|
||||
*/
|
||||
#define ltolower(c) \
|
||||
check_exp(('A' <= (c) && (c) <= 'Z') || (c) == ((c) | ('A' ^ 'a')), \
|
||||
(c) | ('A' ^ 'a'))
|
||||
|
||||
|
||||
/* one entry for each character and for -1 (EOZ) */
|
||||
LUAI_DDEC(const lu_byte luai_ctype_[UCHAR_MAX + 2];)
|
||||
|
||||
|
||||
#else /* }{ */
|
||||
|
||||
/*
|
||||
** use standard C ctypes
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
|
||||
#define lislalpha(c) (isalpha(c) || (c) == '_')
|
||||
#define lislalnum(c) (isalnum(c) || (c) == '_')
|
||||
#define lisdigit(c) (isdigit(c))
|
||||
#define lisspace(c) (isspace(c))
|
||||
#define lisprint(c) (isprint(c))
|
||||
#define lisxdigit(c) (isxdigit(c))
|
||||
|
||||
#define ltolower(c) (tolower(c))
|
||||
|
||||
#endif /* } */
|
||||
|
||||
#endif
|
||||
|
||||
483
src/lua/lua-5.4.8/src/ldblib.c
Normal file
@@ -0,0 +1,483 @@
|
||||
/*
|
||||
** $Id: ldblib.c $
|
||||
** Interface from Lua to its debug API
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#define ldblib_c
|
||||
#define LUA_LIB
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lauxlib.h"
|
||||
#include "lualib.h"
|
||||
|
||||
|
||||
/*
|
||||
** The hook table at registry[HOOKKEY] maps threads to their current
|
||||
** hook function.
|
||||
*/
|
||||
static const char *const HOOKKEY = "_HOOKKEY";
|
||||
|
||||
|
||||
/*
|
||||
** If L1 != L, L1 can be in any state, and therefore there are no
|
||||
** guarantees about its stack space; any push in L1 must be
|
||||
** checked.
|
||||
*/
|
||||
static void checkstack (lua_State *L, lua_State *L1, int n) {
|
||||
if (l_unlikely(L != L1 && !lua_checkstack(L1, n)))
|
||||
luaL_error(L, "stack overflow");
|
||||
}
|
||||
|
||||
|
||||
static int db_getregistry (lua_State *L) {
|
||||
lua_pushvalue(L, LUA_REGISTRYINDEX);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int db_getmetatable (lua_State *L) {
|
||||
luaL_checkany(L, 1);
|
||||
if (!lua_getmetatable(L, 1)) {
|
||||
lua_pushnil(L); /* no metatable */
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int db_setmetatable (lua_State *L) {
|
||||
int t = lua_type(L, 2);
|
||||
luaL_argexpected(L, t == LUA_TNIL || t == LUA_TTABLE, 2, "nil or table");
|
||||
lua_settop(L, 2);
|
||||
lua_setmetatable(L, 1);
|
||||
return 1; /* return 1st argument */
|
||||
}
|
||||
|
||||
|
||||
static int db_getuservalue (lua_State *L) {
|
||||
int n = (int)luaL_optinteger(L, 2, 1);
|
||||
if (lua_type(L, 1) != LUA_TUSERDATA)
|
||||
luaL_pushfail(L);
|
||||
else if (lua_getiuservalue(L, 1, n) != LUA_TNONE) {
|
||||
lua_pushboolean(L, 1);
|
||||
return 2;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int db_setuservalue (lua_State *L) {
|
||||
int n = (int)luaL_optinteger(L, 3, 1);
|
||||
luaL_checktype(L, 1, LUA_TUSERDATA);
|
||||
luaL_checkany(L, 2);
|
||||
lua_settop(L, 2);
|
||||
if (!lua_setiuservalue(L, 1, n))
|
||||
luaL_pushfail(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Auxiliary function used by several library functions: check for
|
||||
** an optional thread as function's first argument and set 'arg' with
|
||||
** 1 if this argument is present (so that functions can skip it to
|
||||
** access their other arguments)
|
||||
*/
|
||||
static lua_State *getthread (lua_State *L, int *arg) {
|
||||
if (lua_isthread(L, 1)) {
|
||||
*arg = 1;
|
||||
return lua_tothread(L, 1);
|
||||
}
|
||||
else {
|
||||
*arg = 0;
|
||||
return L; /* function will operate over current thread */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Variations of 'lua_settable', used by 'db_getinfo' to put results
|
||||
** from 'lua_getinfo' into result table. Key is always a string;
|
||||
** value can be a string, an int, or a boolean.
|
||||
*/
|
||||
static void settabss (lua_State *L, const char *k, const char *v) {
|
||||
lua_pushstring(L, v);
|
||||
lua_setfield(L, -2, k);
|
||||
}
|
||||
|
||||
static void settabsi (lua_State *L, const char *k, int v) {
|
||||
lua_pushinteger(L, v);
|
||||
lua_setfield(L, -2, k);
|
||||
}
|
||||
|
||||
static void settabsb (lua_State *L, const char *k, int v) {
|
||||
lua_pushboolean(L, v);
|
||||
lua_setfield(L, -2, k);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** In function 'db_getinfo', the call to 'lua_getinfo' may push
|
||||
** results on the stack; later it creates the result table to put
|
||||
** these objects. Function 'treatstackoption' puts the result from
|
||||
** 'lua_getinfo' on top of the result table so that it can call
|
||||
** 'lua_setfield'.
|
||||
*/
|
||||
static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) {
|
||||
if (L == L1)
|
||||
lua_rotate(L, -2, 1); /* exchange object and table */
|
||||
else
|
||||
lua_xmove(L1, L, 1); /* move object to the "main" stack */
|
||||
lua_setfield(L, -2, fname); /* put object into table */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Calls 'lua_getinfo' and collects all results in a new table.
|
||||
** L1 needs stack space for an optional input (function) plus
|
||||
** two optional outputs (function and line table) from function
|
||||
** 'lua_getinfo'.
|
||||
*/
|
||||
static int db_getinfo (lua_State *L) {
|
||||
lua_Debug ar;
|
||||
int arg;
|
||||
lua_State *L1 = getthread(L, &arg);
|
||||
const char *options = luaL_optstring(L, arg+2, "flnSrtu");
|
||||
checkstack(L, L1, 3);
|
||||
luaL_argcheck(L, options[0] != '>', arg + 2, "invalid option '>'");
|
||||
if (lua_isfunction(L, arg + 1)) { /* info about a function? */
|
||||
options = lua_pushfstring(L, ">%s", options); /* add '>' to 'options' */
|
||||
lua_pushvalue(L, arg + 1); /* move function to 'L1' stack */
|
||||
lua_xmove(L, L1, 1);
|
||||
}
|
||||
else { /* stack level */
|
||||
if (!lua_getstack(L1, (int)luaL_checkinteger(L, arg + 1), &ar)) {
|
||||
luaL_pushfail(L); /* level out of range */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (!lua_getinfo(L1, options, &ar))
|
||||
return luaL_argerror(L, arg+2, "invalid option");
|
||||
lua_newtable(L); /* table to collect results */
|
||||
if (strchr(options, 'S')) {
|
||||
lua_pushlstring(L, ar.source, ar.srclen);
|
||||
lua_setfield(L, -2, "source");
|
||||
settabss(L, "short_src", ar.short_src);
|
||||
settabsi(L, "linedefined", ar.linedefined);
|
||||
settabsi(L, "lastlinedefined", ar.lastlinedefined);
|
||||
settabss(L, "what", ar.what);
|
||||
}
|
||||
if (strchr(options, 'l'))
|
||||
settabsi(L, "currentline", ar.currentline);
|
||||
if (strchr(options, 'u')) {
|
||||
settabsi(L, "nups", ar.nups);
|
||||
settabsi(L, "nparams", ar.nparams);
|
||||
settabsb(L, "isvararg", ar.isvararg);
|
||||
}
|
||||
if (strchr(options, 'n')) {
|
||||
settabss(L, "name", ar.name);
|
||||
settabss(L, "namewhat", ar.namewhat);
|
||||
}
|
||||
if (strchr(options, 'r')) {
|
||||
settabsi(L, "ftransfer", ar.ftransfer);
|
||||
settabsi(L, "ntransfer", ar.ntransfer);
|
||||
}
|
||||
if (strchr(options, 't'))
|
||||
settabsb(L, "istailcall", ar.istailcall);
|
||||
if (strchr(options, 'L'))
|
||||
treatstackoption(L, L1, "activelines");
|
||||
if (strchr(options, 'f'))
|
||||
treatstackoption(L, L1, "func");
|
||||
return 1; /* return table */
|
||||
}
|
||||
|
||||
|
||||
static int db_getlocal (lua_State *L) {
|
||||
int arg;
|
||||
lua_State *L1 = getthread(L, &arg);
|
||||
int nvar = (int)luaL_checkinteger(L, arg + 2); /* local-variable index */
|
||||
if (lua_isfunction(L, arg + 1)) { /* function argument? */
|
||||
lua_pushvalue(L, arg + 1); /* push function */
|
||||
lua_pushstring(L, lua_getlocal(L, NULL, nvar)); /* push local name */
|
||||
return 1; /* return only name (there is no value) */
|
||||
}
|
||||
else { /* stack-level argument */
|
||||
lua_Debug ar;
|
||||
const char *name;
|
||||
int level = (int)luaL_checkinteger(L, arg + 1);
|
||||
if (l_unlikely(!lua_getstack(L1, level, &ar))) /* out of range? */
|
||||
return luaL_argerror(L, arg+1, "level out of range");
|
||||
checkstack(L, L1, 1);
|
||||
name = lua_getlocal(L1, &ar, nvar);
|
||||
if (name) {
|
||||
lua_xmove(L1, L, 1); /* move local value */
|
||||
lua_pushstring(L, name); /* push name */
|
||||
lua_rotate(L, -2, 1); /* re-order */
|
||||
return 2;
|
||||
}
|
||||
else {
|
||||
luaL_pushfail(L); /* no name (nor value) */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int db_setlocal (lua_State *L) {
|
||||
int arg;
|
||||
const char *name;
|
||||
lua_State *L1 = getthread(L, &arg);
|
||||
lua_Debug ar;
|
||||
int level = (int)luaL_checkinteger(L, arg + 1);
|
||||
int nvar = (int)luaL_checkinteger(L, arg + 2);
|
||||
if (l_unlikely(!lua_getstack(L1, level, &ar))) /* out of range? */
|
||||
return luaL_argerror(L, arg+1, "level out of range");
|
||||
luaL_checkany(L, arg+3);
|
||||
lua_settop(L, arg+3);
|
||||
checkstack(L, L1, 1);
|
||||
lua_xmove(L, L1, 1);
|
||||
name = lua_setlocal(L1, &ar, nvar);
|
||||
if (name == NULL)
|
||||
lua_pop(L1, 1); /* pop value (if not popped by 'lua_setlocal') */
|
||||
lua_pushstring(L, name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** get (if 'get' is true) or set an upvalue from a closure
|
||||
*/
|
||||
static int auxupvalue (lua_State *L, int get) {
|
||||
const char *name;
|
||||
int n = (int)luaL_checkinteger(L, 2); /* upvalue index */
|
||||
luaL_checktype(L, 1, LUA_TFUNCTION); /* closure */
|
||||
name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n);
|
||||
if (name == NULL) return 0;
|
||||
lua_pushstring(L, name);
|
||||
lua_insert(L, -(get+1)); /* no-op if get is false */
|
||||
return get + 1;
|
||||
}
|
||||
|
||||
|
||||
static int db_getupvalue (lua_State *L) {
|
||||
return auxupvalue(L, 1);
|
||||
}
|
||||
|
||||
|
||||
static int db_setupvalue (lua_State *L) {
|
||||
luaL_checkany(L, 3);
|
||||
return auxupvalue(L, 0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Check whether a given upvalue from a given closure exists and
|
||||
** returns its index
|
||||
*/
|
||||
static void *checkupval (lua_State *L, int argf, int argnup, int *pnup) {
|
||||
void *id;
|
||||
int nup = (int)luaL_checkinteger(L, argnup); /* upvalue index */
|
||||
luaL_checktype(L, argf, LUA_TFUNCTION); /* closure */
|
||||
id = lua_upvalueid(L, argf, nup);
|
||||
if (pnup) {
|
||||
luaL_argcheck(L, id != NULL, argnup, "invalid upvalue index");
|
||||
*pnup = nup;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
static int db_upvalueid (lua_State *L) {
|
||||
void *id = checkupval(L, 1, 2, NULL);
|
||||
if (id != NULL)
|
||||
lua_pushlightuserdata(L, id);
|
||||
else
|
||||
luaL_pushfail(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int db_upvaluejoin (lua_State *L) {
|
||||
int n1, n2;
|
||||
checkupval(L, 1, 2, &n1);
|
||||
checkupval(L, 3, 4, &n2);
|
||||
luaL_argcheck(L, !lua_iscfunction(L, 1), 1, "Lua function expected");
|
||||
luaL_argcheck(L, !lua_iscfunction(L, 3), 3, "Lua function expected");
|
||||
lua_upvaluejoin(L, 1, n1, 3, n2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Call hook function registered at hook table for the current
|
||||
** thread (if there is one)
|
||||
*/
|
||||
static void hookf (lua_State *L, lua_Debug *ar) {
|
||||
static const char *const hooknames[] =
|
||||
{"call", "return", "line", "count", "tail call"};
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, HOOKKEY);
|
||||
lua_pushthread(L);
|
||||
if (lua_rawget(L, -2) == LUA_TFUNCTION) { /* is there a hook function? */
|
||||
lua_pushstring(L, hooknames[(int)ar->event]); /* push event name */
|
||||
if (ar->currentline >= 0)
|
||||
lua_pushinteger(L, ar->currentline); /* push current line */
|
||||
else lua_pushnil(L);
|
||||
lua_assert(lua_getinfo(L, "lS", ar));
|
||||
lua_call(L, 2, 0); /* call hook function */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Convert a string mask (for 'sethook') into a bit mask
|
||||
*/
|
||||
static int makemask (const char *smask, int count) {
|
||||
int mask = 0;
|
||||
if (strchr(smask, 'c')) mask |= LUA_MASKCALL;
|
||||
if (strchr(smask, 'r')) mask |= LUA_MASKRET;
|
||||
if (strchr(smask, 'l')) mask |= LUA_MASKLINE;
|
||||
if (count > 0) mask |= LUA_MASKCOUNT;
|
||||
return mask;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Convert a bit mask (for 'gethook') into a string mask
|
||||
*/
|
||||
static char *unmakemask (int mask, char *smask) {
|
||||
int i = 0;
|
||||
if (mask & LUA_MASKCALL) smask[i++] = 'c';
|
||||
if (mask & LUA_MASKRET) smask[i++] = 'r';
|
||||
if (mask & LUA_MASKLINE) smask[i++] = 'l';
|
||||
smask[i] = '\0';
|
||||
return smask;
|
||||
}
|
||||
|
||||
|
||||
static int db_sethook (lua_State *L) {
|
||||
int arg, mask, count;
|
||||
lua_Hook func;
|
||||
lua_State *L1 = getthread(L, &arg);
|
||||
if (lua_isnoneornil(L, arg+1)) { /* no hook? */
|
||||
lua_settop(L, arg+1);
|
||||
func = NULL; mask = 0; count = 0; /* turn off hooks */
|
||||
}
|
||||
else {
|
||||
const char *smask = luaL_checkstring(L, arg+2);
|
||||
luaL_checktype(L, arg+1, LUA_TFUNCTION);
|
||||
count = (int)luaL_optinteger(L, arg + 3, 0);
|
||||
func = hookf; mask = makemask(smask, count);
|
||||
}
|
||||
if (!luaL_getsubtable(L, LUA_REGISTRYINDEX, HOOKKEY)) {
|
||||
/* table just created; initialize it */
|
||||
lua_pushliteral(L, "k");
|
||||
lua_setfield(L, -2, "__mode"); /** hooktable.__mode = "k" */
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setmetatable(L, -2); /* metatable(hooktable) = hooktable */
|
||||
}
|
||||
checkstack(L, L1, 1);
|
||||
lua_pushthread(L1); lua_xmove(L1, L, 1); /* key (thread) */
|
||||
lua_pushvalue(L, arg + 1); /* value (hook function) */
|
||||
lua_rawset(L, -3); /* hooktable[L1] = new Lua hook */
|
||||
lua_sethook(L1, func, mask, count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int db_gethook (lua_State *L) {
|
||||
int arg;
|
||||
lua_State *L1 = getthread(L, &arg);
|
||||
char buff[5];
|
||||
int mask = lua_gethookmask(L1);
|
||||
lua_Hook hook = lua_gethook(L1);
|
||||
if (hook == NULL) { /* no hook? */
|
||||
luaL_pushfail(L);
|
||||
return 1;
|
||||
}
|
||||
else if (hook != hookf) /* external hook? */
|
||||
lua_pushliteral(L, "external hook");
|
||||
else { /* hook table must exist */
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, HOOKKEY);
|
||||
checkstack(L, L1, 1);
|
||||
lua_pushthread(L1); lua_xmove(L1, L, 1);
|
||||
lua_rawget(L, -2); /* 1st result = hooktable[L1] */
|
||||
lua_remove(L, -2); /* remove hook table */
|
||||
}
|
||||
lua_pushstring(L, unmakemask(mask, buff)); /* 2nd result = mask */
|
||||
lua_pushinteger(L, lua_gethookcount(L1)); /* 3rd result = count */
|
||||
return 3;
|
||||
}
|
||||
|
||||
|
||||
static int db_debug (lua_State *L) {
|
||||
for (;;) {
|
||||
char buffer[250];
|
||||
lua_writestringerror("%s", "lua_debug> ");
|
||||
if (fgets(buffer, sizeof(buffer), stdin) == NULL ||
|
||||
strcmp(buffer, "cont\n") == 0)
|
||||
return 0;
|
||||
if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") ||
|
||||
lua_pcall(L, 0, 0, 0))
|
||||
lua_writestringerror("%s\n", luaL_tolstring(L, -1, NULL));
|
||||
lua_settop(L, 0); /* remove eventual returns */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int db_traceback (lua_State *L) {
|
||||
int arg;
|
||||
lua_State *L1 = getthread(L, &arg);
|
||||
const char *msg = lua_tostring(L, arg + 1);
|
||||
if (msg == NULL && !lua_isnoneornil(L, arg + 1)) /* non-string 'msg'? */
|
||||
lua_pushvalue(L, arg + 1); /* return it untouched */
|
||||
else {
|
||||
int level = (int)luaL_optinteger(L, arg + 2, (L == L1) ? 1 : 0);
|
||||
luaL_traceback(L, L1, msg, level);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int db_setcstacklimit (lua_State *L) {
|
||||
int limit = (int)luaL_checkinteger(L, 1);
|
||||
int res = lua_setcstacklimit(L, limit);
|
||||
lua_pushinteger(L, res);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static const luaL_Reg dblib[] = {
|
||||
{"debug", db_debug},
|
||||
{"getuservalue", db_getuservalue},
|
||||
{"gethook", db_gethook},
|
||||
{"getinfo", db_getinfo},
|
||||
{"getlocal", db_getlocal},
|
||||
{"getregistry", db_getregistry},
|
||||
{"getmetatable", db_getmetatable},
|
||||
{"getupvalue", db_getupvalue},
|
||||
{"upvaluejoin", db_upvaluejoin},
|
||||
{"upvalueid", db_upvalueid},
|
||||
{"setuservalue", db_setuservalue},
|
||||
{"sethook", db_sethook},
|
||||
{"setlocal", db_setlocal},
|
||||
{"setmetatable", db_setmetatable},
|
||||
{"setupvalue", db_setupvalue},
|
||||
{"traceback", db_traceback},
|
||||
{"setcstacklimit", db_setcstacklimit},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
LUAMOD_API int luaopen_debug (lua_State *L) {
|
||||
luaL_newlib(L, dblib);
|
||||
return 1;
|
||||
}
|
||||
|
||||
971
src/lua/lua-5.4.8/src/ldebug.c
Normal file
@@ -0,0 +1,971 @@
|
||||
/*
|
||||
** $Id: ldebug.c $
|
||||
** Debug Interface
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#define ldebug_c
|
||||
#define LUA_CORE
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lapi.h"
|
||||
#include "lcode.h"
|
||||
#include "ldebug.h"
|
||||
#include "ldo.h"
|
||||
#include "lfunc.h"
|
||||
#include "lobject.h"
|
||||
#include "lopcodes.h"
|
||||
#include "lstate.h"
|
||||
#include "lstring.h"
|
||||
#include "ltable.h"
|
||||
#include "ltm.h"
|
||||
#include "lvm.h"
|
||||
|
||||
|
||||
|
||||
#define LuaClosure(f) ((f) != NULL && (f)->c.tt == LUA_VLCL)
|
||||
|
||||
|
||||
static const char *funcnamefromcall (lua_State *L, CallInfo *ci,
|
||||
const char **name);
|
||||
|
||||
static const char strlocal[] = "local";
|
||||
static const char strupval[] = "upvalue";
|
||||
|
||||
|
||||
static int currentpc (CallInfo *ci) {
|
||||
lua_assert(isLua(ci));
|
||||
return pcRel(ci->u.l.savedpc, ci_func(ci)->p);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Get a "base line" to find the line corresponding to an instruction.
|
||||
** Base lines are regularly placed at MAXIWTHABS intervals, so usually
|
||||
** an integer division gets the right place. When the source file has
|
||||
** large sequences of empty/comment lines, it may need extra entries,
|
||||
** so the original estimate needs a correction.
|
||||
** If the original estimate is -1, the initial 'if' ensures that the
|
||||
** 'while' will run at least once.
|
||||
** The assertion that the estimate is a lower bound for the correct base
|
||||
** is valid as long as the debug info has been generated with the same
|
||||
** value for MAXIWTHABS or smaller. (Previous releases use a little
|
||||
** smaller value.)
|
||||
*/
|
||||
static int getbaseline (const Proto *f, int pc, int *basepc) {
|
||||
if (f->sizeabslineinfo == 0 || pc < f->abslineinfo[0].pc) {
|
||||
*basepc = -1; /* start from the beginning */
|
||||
return f->linedefined;
|
||||
}
|
||||
else {
|
||||
int i = cast_uint(pc) / MAXIWTHABS - 1; /* get an estimate */
|
||||
/* estimate must be a lower bound of the correct base */
|
||||
lua_assert(i < 0 ||
|
||||
(i < f->sizeabslineinfo && f->abslineinfo[i].pc <= pc));
|
||||
while (i + 1 < f->sizeabslineinfo && pc >= f->abslineinfo[i + 1].pc)
|
||||
i++; /* low estimate; adjust it */
|
||||
*basepc = f->abslineinfo[i].pc;
|
||||
return f->abslineinfo[i].line;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Get the line corresponding to instruction 'pc' in function 'f';
|
||||
** first gets a base line and from there does the increments until
|
||||
** the desired instruction.
|
||||
*/
|
||||
int luaG_getfuncline (const Proto *f, int pc) {
|
||||
if (f->lineinfo == NULL) /* no debug information? */
|
||||
return -1;
|
||||
else {
|
||||
int basepc;
|
||||
int baseline = getbaseline(f, pc, &basepc);
|
||||
while (basepc++ < pc) { /* walk until given instruction */
|
||||
lua_assert(f->lineinfo[basepc] != ABSLINEINFO);
|
||||
baseline += f->lineinfo[basepc]; /* correct line */
|
||||
}
|
||||
return baseline;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int getcurrentline (CallInfo *ci) {
|
||||
return luaG_getfuncline(ci_func(ci)->p, currentpc(ci));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Set 'trap' for all active Lua frames.
|
||||
** This function can be called during a signal, under "reasonable"
|
||||
** assumptions. A new 'ci' is completely linked in the list before it
|
||||
** becomes part of the "active" list, and we assume that pointers are
|
||||
** atomic; see comment in next function.
|
||||
** (A compiler doing interprocedural optimizations could, theoretically,
|
||||
** reorder memory writes in such a way that the list could be
|
||||
** temporarily broken while inserting a new element. We simply assume it
|
||||
** has no good reasons to do that.)
|
||||
*/
|
||||
static void settraps (CallInfo *ci) {
|
||||
for (; ci != NULL; ci = ci->previous)
|
||||
if (isLua(ci))
|
||||
ci->u.l.trap = 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** This function can be called during a signal, under "reasonable"
|
||||
** assumptions.
|
||||
** Fields 'basehookcount' and 'hookcount' (set by 'resethookcount')
|
||||
** are for debug only, and it is no problem if they get arbitrary
|
||||
** values (causes at most one wrong hook call). 'hookmask' is an atomic
|
||||
** value. We assume that pointers are atomic too (e.g., gcc ensures that
|
||||
** for all platforms where it runs). Moreover, 'hook' is always checked
|
||||
** before being called (see 'luaD_hook').
|
||||
*/
|
||||
LUA_API void lua_sethook (lua_State *L, lua_Hook func, int mask, int count) {
|
||||
if (func == NULL || mask == 0) { /* turn off hooks? */
|
||||
mask = 0;
|
||||
func = NULL;
|
||||
}
|
||||
L->hook = func;
|
||||
L->basehookcount = count;
|
||||
resethookcount(L);
|
||||
L->hookmask = cast_byte(mask);
|
||||
if (mask)
|
||||
settraps(L->ci); /* to trace inside 'luaV_execute' */
|
||||
}
|
||||
|
||||
|
||||
LUA_API lua_Hook lua_gethook (lua_State *L) {
|
||||
return L->hook;
|
||||
}
|
||||
|
||||
|
||||
LUA_API int lua_gethookmask (lua_State *L) {
|
||||
return L->hookmask;
|
||||
}
|
||||
|
||||
|
||||
LUA_API int lua_gethookcount (lua_State *L) {
|
||||
return L->basehookcount;
|
||||
}
|
||||
|
||||
|
||||
LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) {
|
||||
int status;
|
||||
CallInfo *ci;
|
||||
if (level < 0) return 0; /* invalid (negative) level */
|
||||
lua_lock(L);
|
||||
for (ci = L->ci; level > 0 && ci != &L->base_ci; ci = ci->previous)
|
||||
level--;
|
||||
if (level == 0 && ci != &L->base_ci) { /* level found? */
|
||||
status = 1;
|
||||
ar->i_ci = ci;
|
||||
}
|
||||
else status = 0; /* no such level */
|
||||
lua_unlock(L);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
static const char *upvalname (const Proto *p, int uv) {
|
||||
TString *s = check_exp(uv < p->sizeupvalues, p->upvalues[uv].name);
|
||||
if (s == NULL) return "?";
|
||||
else return getstr(s);
|
||||
}
|
||||
|
||||
|
||||
static const char *findvararg (CallInfo *ci, int n, StkId *pos) {
|
||||
if (clLvalue(s2v(ci->func.p))->p->is_vararg) {
|
||||
int nextra = ci->u.l.nextraargs;
|
||||
if (n >= -nextra) { /* 'n' is negative */
|
||||
*pos = ci->func.p - nextra - (n + 1);
|
||||
return "(vararg)"; /* generic name for any vararg */
|
||||
}
|
||||
}
|
||||
return NULL; /* no such vararg */
|
||||
}
|
||||
|
||||
|
||||
const char *luaG_findlocal (lua_State *L, CallInfo *ci, int n, StkId *pos) {
|
||||
StkId base = ci->func.p + 1;
|
||||
const char *name = NULL;
|
||||
if (isLua(ci)) {
|
||||
if (n < 0) /* access to vararg values? */
|
||||
return findvararg(ci, n, pos);
|
||||
else
|
||||
name = luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci));
|
||||
}
|
||||
if (name == NULL) { /* no 'standard' name? */
|
||||
StkId limit = (ci == L->ci) ? L->top.p : ci->next->func.p;
|
||||
if (limit - base >= n && n > 0) { /* is 'n' inside 'ci' stack? */
|
||||
/* generic name for any valid slot */
|
||||
name = isLua(ci) ? "(temporary)" : "(C temporary)";
|
||||
}
|
||||
else
|
||||
return NULL; /* no name */
|
||||
}
|
||||
if (pos)
|
||||
*pos = base + (n - 1);
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) {
|
||||
const char *name;
|
||||
lua_lock(L);
|
||||
if (ar == NULL) { /* information about non-active function? */
|
||||
if (!isLfunction(s2v(L->top.p - 1))) /* not a Lua function? */
|
||||
name = NULL;
|
||||
else /* consider live variables at function start (parameters) */
|
||||
name = luaF_getlocalname(clLvalue(s2v(L->top.p - 1))->p, n, 0);
|
||||
}
|
||||
else { /* active function; get information through 'ar' */
|
||||
StkId pos = NULL; /* to avoid warnings */
|
||||
name = luaG_findlocal(L, ar->i_ci, n, &pos);
|
||||
if (name) {
|
||||
setobjs2s(L, L->top.p, pos);
|
||||
api_incr_top(L);
|
||||
}
|
||||
}
|
||||
lua_unlock(L);
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) {
|
||||
StkId pos = NULL; /* to avoid warnings */
|
||||
const char *name;
|
||||
lua_lock(L);
|
||||
name = luaG_findlocal(L, ar->i_ci, n, &pos);
|
||||
if (name) {
|
||||
setobjs2s(L, pos, L->top.p - 1);
|
||||
L->top.p--; /* pop value */
|
||||
}
|
||||
lua_unlock(L);
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
static void funcinfo (lua_Debug *ar, Closure *cl) {
|
||||
if (!LuaClosure(cl)) {
|
||||
ar->source = "=[C]";
|
||||
ar->srclen = LL("=[C]");
|
||||
ar->linedefined = -1;
|
||||
ar->lastlinedefined = -1;
|
||||
ar->what = "C";
|
||||
}
|
||||
else {
|
||||
const Proto *p = cl->l.p;
|
||||
if (p->source) {
|
||||
ar->source = getstr(p->source);
|
||||
ar->srclen = tsslen(p->source);
|
||||
}
|
||||
else {
|
||||
ar->source = "=?";
|
||||
ar->srclen = LL("=?");
|
||||
}
|
||||
ar->linedefined = p->linedefined;
|
||||
ar->lastlinedefined = p->lastlinedefined;
|
||||
ar->what = (ar->linedefined == 0) ? "main" : "Lua";
|
||||
}
|
||||
luaO_chunkid(ar->short_src, ar->source, ar->srclen);
|
||||
}
|
||||
|
||||
|
||||
static int nextline (const Proto *p, int currentline, int pc) {
|
||||
if (p->lineinfo[pc] != ABSLINEINFO)
|
||||
return currentline + p->lineinfo[pc];
|
||||
else
|
||||
return luaG_getfuncline(p, pc);
|
||||
}
|
||||
|
||||
|
||||
static void collectvalidlines (lua_State *L, Closure *f) {
|
||||
if (!LuaClosure(f)) {
|
||||
setnilvalue(s2v(L->top.p));
|
||||
api_incr_top(L);
|
||||
}
|
||||
else {
|
||||
const Proto *p = f->l.p;
|
||||
int currentline = p->linedefined;
|
||||
Table *t = luaH_new(L); /* new table to store active lines */
|
||||
sethvalue2s(L, L->top.p, t); /* push it on stack */
|
||||
api_incr_top(L);
|
||||
if (p->lineinfo != NULL) { /* proto with debug information? */
|
||||
int i;
|
||||
TValue v;
|
||||
setbtvalue(&v); /* boolean 'true' to be the value of all indices */
|
||||
if (!p->is_vararg) /* regular function? */
|
||||
i = 0; /* consider all instructions */
|
||||
else { /* vararg function */
|
||||
lua_assert(GET_OPCODE(p->code[0]) == OP_VARARGPREP);
|
||||
currentline = nextline(p, currentline, 0);
|
||||
i = 1; /* skip first instruction (OP_VARARGPREP) */
|
||||
}
|
||||
for (; i < p->sizelineinfo; i++) { /* for each instruction */
|
||||
currentline = nextline(p, currentline, i); /* get its line */
|
||||
luaH_setint(L, t, currentline, &v); /* table[line] = true */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) {
|
||||
/* calling function is a known function? */
|
||||
if (ci != NULL && !(ci->callstatus & CIST_TAIL))
|
||||
return funcnamefromcall(L, ci->previous, name);
|
||||
else return NULL; /* no way to find a name */
|
||||
}
|
||||
|
||||
|
||||
static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar,
|
||||
Closure *f, CallInfo *ci) {
|
||||
int status = 1;
|
||||
for (; *what; what++) {
|
||||
switch (*what) {
|
||||
case 'S': {
|
||||
funcinfo(ar, f);
|
||||
break;
|
||||
}
|
||||
case 'l': {
|
||||
ar->currentline = (ci && isLua(ci)) ? getcurrentline(ci) : -1;
|
||||
break;
|
||||
}
|
||||
case 'u': {
|
||||
ar->nups = (f == NULL) ? 0 : f->c.nupvalues;
|
||||
if (!LuaClosure(f)) {
|
||||
ar->isvararg = 1;
|
||||
ar->nparams = 0;
|
||||
}
|
||||
else {
|
||||
ar->isvararg = f->l.p->is_vararg;
|
||||
ar->nparams = f->l.p->numparams;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 't': {
|
||||
ar->istailcall = (ci) ? ci->callstatus & CIST_TAIL : 0;
|
||||
break;
|
||||
}
|
||||
case 'n': {
|
||||
ar->namewhat = getfuncname(L, ci, &ar->name);
|
||||
if (ar->namewhat == NULL) {
|
||||
ar->namewhat = ""; /* not found */
|
||||
ar->name = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'r': {
|
||||
if (ci == NULL || !(ci->callstatus & CIST_TRAN))
|
||||
ar->ftransfer = ar->ntransfer = 0;
|
||||
else {
|
||||
ar->ftransfer = ci->u2.transferinfo.ftransfer;
|
||||
ar->ntransfer = ci->u2.transferinfo.ntransfer;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'L':
|
||||
case 'f': /* handled by lua_getinfo */
|
||||
break;
|
||||
default: status = 0; /* invalid option */
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {
|
||||
int status;
|
||||
Closure *cl;
|
||||
CallInfo *ci;
|
||||
TValue *func;
|
||||
lua_lock(L);
|
||||
if (*what == '>') {
|
||||
ci = NULL;
|
||||
func = s2v(L->top.p - 1);
|
||||
api_check(L, ttisfunction(func), "function expected");
|
||||
what++; /* skip the '>' */
|
||||
L->top.p--; /* pop function */
|
||||
}
|
||||
else {
|
||||
ci = ar->i_ci;
|
||||
func = s2v(ci->func.p);
|
||||
lua_assert(ttisfunction(func));
|
||||
}
|
||||
cl = ttisclosure(func) ? clvalue(func) : NULL;
|
||||
status = auxgetinfo(L, what, ar, cl, ci);
|
||||
if (strchr(what, 'f')) {
|
||||
setobj2s(L, L->top.p, func);
|
||||
api_incr_top(L);
|
||||
}
|
||||
if (strchr(what, 'L'))
|
||||
collectvalidlines(L, cl);
|
||||
lua_unlock(L);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** {======================================================
|
||||
** Symbolic Execution
|
||||
** =======================================================
|
||||
*/
|
||||
|
||||
|
||||
static int filterpc (int pc, int jmptarget) {
|
||||
if (pc < jmptarget) /* is code conditional (inside a jump)? */
|
||||
return -1; /* cannot know who sets that register */
|
||||
else return pc; /* current position sets that register */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Try to find last instruction before 'lastpc' that modified register 'reg'.
|
||||
*/
|
||||
static int findsetreg (const Proto *p, int lastpc, int reg) {
|
||||
int pc;
|
||||
int setreg = -1; /* keep last instruction that changed 'reg' */
|
||||
int jmptarget = 0; /* any code before this address is conditional */
|
||||
if (testMMMode(GET_OPCODE(p->code[lastpc])))
|
||||
lastpc--; /* previous instruction was not actually executed */
|
||||
for (pc = 0; pc < lastpc; pc++) {
|
||||
Instruction i = p->code[pc];
|
||||
OpCode op = GET_OPCODE(i);
|
||||
int a = GETARG_A(i);
|
||||
int change; /* true if current instruction changed 'reg' */
|
||||
switch (op) {
|
||||
case OP_LOADNIL: { /* set registers from 'a' to 'a+b' */
|
||||
int b = GETARG_B(i);
|
||||
change = (a <= reg && reg <= a + b);
|
||||
break;
|
||||
}
|
||||
case OP_TFORCALL: { /* affect all regs above its base */
|
||||
change = (reg >= a + 2);
|
||||
break;
|
||||
}
|
||||
case OP_CALL:
|
||||
case OP_TAILCALL: { /* affect all registers above base */
|
||||
change = (reg >= a);
|
||||
break;
|
||||
}
|
||||
case OP_JMP: { /* doesn't change registers, but changes 'jmptarget' */
|
||||
int b = GETARG_sJ(i);
|
||||
int dest = pc + 1 + b;
|
||||
/* jump does not skip 'lastpc' and is larger than current one? */
|
||||
if (dest <= lastpc && dest > jmptarget)
|
||||
jmptarget = dest; /* update 'jmptarget' */
|
||||
change = 0;
|
||||
break;
|
||||
}
|
||||
default: /* any instruction that sets A */
|
||||
change = (testAMode(op) && reg == a);
|
||||
break;
|
||||
}
|
||||
if (change)
|
||||
setreg = filterpc(pc, jmptarget);
|
||||
}
|
||||
return setreg;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Find a "name" for the constant 'c'.
|
||||
*/
|
||||
static const char *kname (const Proto *p, int index, const char **name) {
|
||||
TValue *kvalue = &p->k[index];
|
||||
if (ttisstring(kvalue)) {
|
||||
*name = getstr(tsvalue(kvalue));
|
||||
return "constant";
|
||||
}
|
||||
else {
|
||||
*name = "?";
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static const char *basicgetobjname (const Proto *p, int *ppc, int reg,
|
||||
const char **name) {
|
||||
int pc = *ppc;
|
||||
*name = luaF_getlocalname(p, reg + 1, pc);
|
||||
if (*name) /* is a local? */
|
||||
return strlocal;
|
||||
/* else try symbolic execution */
|
||||
*ppc = pc = findsetreg(p, pc, reg);
|
||||
if (pc != -1) { /* could find instruction? */
|
||||
Instruction i = p->code[pc];
|
||||
OpCode op = GET_OPCODE(i);
|
||||
switch (op) {
|
||||
case OP_MOVE: {
|
||||
int b = GETARG_B(i); /* move from 'b' to 'a' */
|
||||
if (b < GETARG_A(i))
|
||||
return basicgetobjname(p, ppc, b, name); /* get name for 'b' */
|
||||
break;
|
||||
}
|
||||
case OP_GETUPVAL: {
|
||||
*name = upvalname(p, GETARG_B(i));
|
||||
return strupval;
|
||||
}
|
||||
case OP_LOADK: return kname(p, GETARG_Bx(i), name);
|
||||
case OP_LOADKX: return kname(p, GETARG_Ax(p->code[pc + 1]), name);
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
return NULL; /* could not find reasonable name */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Find a "name" for the register 'c'.
|
||||
*/
|
||||
static void rname (const Proto *p, int pc, int c, const char **name) {
|
||||
const char *what = basicgetobjname(p, &pc, c, name); /* search for 'c' */
|
||||
if (!(what && *what == 'c')) /* did not find a constant name? */
|
||||
*name = "?";
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Find a "name" for a 'C' value in an RK instruction.
|
||||
*/
|
||||
static void rkname (const Proto *p, int pc, Instruction i, const char **name) {
|
||||
int c = GETARG_C(i); /* key index */
|
||||
if (GETARG_k(i)) /* is 'c' a constant? */
|
||||
kname(p, c, name);
|
||||
else /* 'c' is a register */
|
||||
rname(p, pc, c, name);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Check whether table being indexed by instruction 'i' is the
|
||||
** environment '_ENV'. If the table is an upvalue, get its name;
|
||||
** otherwise, find some "name" for the table and check whether
|
||||
** that name is the name of a local variable (and not, for instance,
|
||||
** a string). Then check that, if there is a name, it is '_ENV'.
|
||||
*/
|
||||
static const char *isEnv (const Proto *p, int pc, Instruction i, int isup) {
|
||||
int t = GETARG_B(i); /* table index */
|
||||
const char *name; /* name of indexed variable */
|
||||
if (isup) /* is 't' an upvalue? */
|
||||
name = upvalname(p, t);
|
||||
else { /* 't' is a register */
|
||||
const char *what = basicgetobjname(p, &pc, t, &name);
|
||||
if (what != strlocal && what != strupval)
|
||||
name = NULL; /* cannot be the variable _ENV */
|
||||
}
|
||||
return (name && strcmp(name, LUA_ENV) == 0) ? "global" : "field";
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Extend 'basicgetobjname' to handle table accesses
|
||||
*/
|
||||
static const char *getobjname (const Proto *p, int lastpc, int reg,
|
||||
const char **name) {
|
||||
const char *kind = basicgetobjname(p, &lastpc, reg, name);
|
||||
if (kind != NULL)
|
||||
return kind;
|
||||
else if (lastpc != -1) { /* could find instruction? */
|
||||
Instruction i = p->code[lastpc];
|
||||
OpCode op = GET_OPCODE(i);
|
||||
switch (op) {
|
||||
case OP_GETTABUP: {
|
||||
int k = GETARG_C(i); /* key index */
|
||||
kname(p, k, name);
|
||||
return isEnv(p, lastpc, i, 1);
|
||||
}
|
||||
case OP_GETTABLE: {
|
||||
int k = GETARG_C(i); /* key index */
|
||||
rname(p, lastpc, k, name);
|
||||
return isEnv(p, lastpc, i, 0);
|
||||
}
|
||||
case OP_GETI: {
|
||||
*name = "integer index";
|
||||
return "field";
|
||||
}
|
||||
case OP_GETFIELD: {
|
||||
int k = GETARG_C(i); /* key index */
|
||||
kname(p, k, name);
|
||||
return isEnv(p, lastpc, i, 0);
|
||||
}
|
||||
case OP_SELF: {
|
||||
rkname(p, lastpc, i, name);
|
||||
return "method";
|
||||
}
|
||||
default: break; /* go through to return NULL */
|
||||
}
|
||||
}
|
||||
return NULL; /* could not find reasonable name */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Try to find a name for a function based on the code that called it.
|
||||
** (Only works when function was called by a Lua function.)
|
||||
** Returns what the name is (e.g., "for iterator", "method",
|
||||
** "metamethod") and sets '*name' to point to the name.
|
||||
*/
|
||||
static const char *funcnamefromcode (lua_State *L, const Proto *p,
|
||||
int pc, const char **name) {
|
||||
TMS tm = (TMS)0; /* (initial value avoids warnings) */
|
||||
Instruction i = p->code[pc]; /* calling instruction */
|
||||
switch (GET_OPCODE(i)) {
|
||||
case OP_CALL:
|
||||
case OP_TAILCALL:
|
||||
return getobjname(p, pc, GETARG_A(i), name); /* get function name */
|
||||
case OP_TFORCALL: { /* for iterator */
|
||||
*name = "for iterator";
|
||||
return "for iterator";
|
||||
}
|
||||
/* other instructions can do calls through metamethods */
|
||||
case OP_SELF: case OP_GETTABUP: case OP_GETTABLE:
|
||||
case OP_GETI: case OP_GETFIELD:
|
||||
tm = TM_INDEX;
|
||||
break;
|
||||
case OP_SETTABUP: case OP_SETTABLE: case OP_SETI: case OP_SETFIELD:
|
||||
tm = TM_NEWINDEX;
|
||||
break;
|
||||
case OP_MMBIN: case OP_MMBINI: case OP_MMBINK: {
|
||||
tm = cast(TMS, GETARG_C(i));
|
||||
break;
|
||||
}
|
||||
case OP_UNM: tm = TM_UNM; break;
|
||||
case OP_BNOT: tm = TM_BNOT; break;
|
||||
case OP_LEN: tm = TM_LEN; break;
|
||||
case OP_CONCAT: tm = TM_CONCAT; break;
|
||||
case OP_EQ: tm = TM_EQ; break;
|
||||
/* no cases for OP_EQI and OP_EQK, as they don't call metamethods */
|
||||
case OP_LT: case OP_LTI: case OP_GTI: tm = TM_LT; break;
|
||||
case OP_LE: case OP_LEI: case OP_GEI: tm = TM_LE; break;
|
||||
case OP_CLOSE: case OP_RETURN: tm = TM_CLOSE; break;
|
||||
default:
|
||||
return NULL; /* cannot find a reasonable name */
|
||||
}
|
||||
*name = getshrstr(G(L)->tmname[tm]) + 2;
|
||||
return "metamethod";
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Try to find a name for a function based on how it was called.
|
||||
*/
|
||||
static const char *funcnamefromcall (lua_State *L, CallInfo *ci,
|
||||
const char **name) {
|
||||
if (ci->callstatus & CIST_HOOKED) { /* was it called inside a hook? */
|
||||
*name = "?";
|
||||
return "hook";
|
||||
}
|
||||
else if (ci->callstatus & CIST_FIN) { /* was it called as a finalizer? */
|
||||
*name = "__gc";
|
||||
return "metamethod"; /* report it as such */
|
||||
}
|
||||
else if (isLua(ci))
|
||||
return funcnamefromcode(L, ci_func(ci)->p, currentpc(ci), name);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* }====================================================== */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** Check whether pointer 'o' points to some value in the stack frame of
|
||||
** the current function and, if so, returns its index. Because 'o' may
|
||||
** not point to a value in this stack, we cannot compare it with the
|
||||
** region boundaries (undefined behavior in ISO C).
|
||||
*/
|
||||
static int instack (CallInfo *ci, const TValue *o) {
|
||||
int pos;
|
||||
StkId base = ci->func.p + 1;
|
||||
for (pos = 0; base + pos < ci->top.p; pos++) {
|
||||
if (o == s2v(base + pos))
|
||||
return pos;
|
||||
}
|
||||
return -1; /* not found */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Checks whether value 'o' came from an upvalue. (That can only happen
|
||||
** with instructions OP_GETTABUP/OP_SETTABUP, which operate directly on
|
||||
** upvalues.)
|
||||
*/
|
||||
static const char *getupvalname (CallInfo *ci, const TValue *o,
|
||||
const char **name) {
|
||||
LClosure *c = ci_func(ci);
|
||||
int i;
|
||||
for (i = 0; i < c->nupvalues; i++) {
|
||||
if (c->upvals[i]->v.p == o) {
|
||||
*name = upvalname(c->p, i);
|
||||
return strupval;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static const char *formatvarinfo (lua_State *L, const char *kind,
|
||||
const char *name) {
|
||||
if (kind == NULL)
|
||||
return ""; /* no information */
|
||||
else
|
||||
return luaO_pushfstring(L, " (%s '%s')", kind, name);
|
||||
}
|
||||
|
||||
/*
|
||||
** Build a string with a "description" for the value 'o', such as
|
||||
** "variable 'x'" or "upvalue 'y'".
|
||||
*/
|
||||
static const char *varinfo (lua_State *L, const TValue *o) {
|
||||
CallInfo *ci = L->ci;
|
||||
const char *name = NULL; /* to avoid warnings */
|
||||
const char *kind = NULL;
|
||||
if (isLua(ci)) {
|
||||
kind = getupvalname(ci, o, &name); /* check whether 'o' is an upvalue */
|
||||
if (!kind) { /* not an upvalue? */
|
||||
int reg = instack(ci, o); /* try a register */
|
||||
if (reg >= 0) /* is 'o' a register? */
|
||||
kind = getobjname(ci_func(ci)->p, currentpc(ci), reg, &name);
|
||||
}
|
||||
}
|
||||
return formatvarinfo(L, kind, name);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Raise a type error
|
||||
*/
|
||||
static l_noret typeerror (lua_State *L, const TValue *o, const char *op,
|
||||
const char *extra) {
|
||||
const char *t = luaT_objtypename(L, o);
|
||||
luaG_runerror(L, "attempt to %s a %s value%s", op, t, extra);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Raise a type error with "standard" information about the faulty
|
||||
** object 'o' (using 'varinfo').
|
||||
*/
|
||||
l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) {
|
||||
typeerror(L, o, op, varinfo(L, o));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Raise an error for calling a non-callable object. Try to find a name
|
||||
** for the object based on how it was called ('funcnamefromcall'); if it
|
||||
** cannot get a name there, try 'varinfo'.
|
||||
*/
|
||||
l_noret luaG_callerror (lua_State *L, const TValue *o) {
|
||||
CallInfo *ci = L->ci;
|
||||
const char *name = NULL; /* to avoid warnings */
|
||||
const char *kind = funcnamefromcall(L, ci, &name);
|
||||
const char *extra = kind ? formatvarinfo(L, kind, name) : varinfo(L, o);
|
||||
typeerror(L, o, "call", extra);
|
||||
}
|
||||
|
||||
|
||||
l_noret luaG_forerror (lua_State *L, const TValue *o, const char *what) {
|
||||
luaG_runerror(L, "bad 'for' %s (number expected, got %s)",
|
||||
what, luaT_objtypename(L, o));
|
||||
}
|
||||
|
||||
|
||||
l_noret luaG_concaterror (lua_State *L, const TValue *p1, const TValue *p2) {
|
||||
if (ttisstring(p1) || cvt2str(p1)) p1 = p2;
|
||||
luaG_typeerror(L, p1, "concatenate");
|
||||
}
|
||||
|
||||
|
||||
l_noret luaG_opinterror (lua_State *L, const TValue *p1,
|
||||
const TValue *p2, const char *msg) {
|
||||
if (!ttisnumber(p1)) /* first operand is wrong? */
|
||||
p2 = p1; /* now second is wrong */
|
||||
luaG_typeerror(L, p2, msg);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Error when both values are convertible to numbers, but not to integers
|
||||
*/
|
||||
l_noret luaG_tointerror (lua_State *L, const TValue *p1, const TValue *p2) {
|
||||
lua_Integer temp;
|
||||
if (!luaV_tointegerns(p1, &temp, LUA_FLOORN2I))
|
||||
p2 = p1;
|
||||
luaG_runerror(L, "number%s has no integer representation", varinfo(L, p2));
|
||||
}
|
||||
|
||||
|
||||
l_noret luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) {
|
||||
const char *t1 = luaT_objtypename(L, p1);
|
||||
const char *t2 = luaT_objtypename(L, p2);
|
||||
if (strcmp(t1, t2) == 0)
|
||||
luaG_runerror(L, "attempt to compare two %s values", t1);
|
||||
else
|
||||
luaG_runerror(L, "attempt to compare %s with %s", t1, t2);
|
||||
}
|
||||
|
||||
|
||||
/* add src:line information to 'msg' */
|
||||
const char *luaG_addinfo (lua_State *L, const char *msg, TString *src,
|
||||
int line) {
|
||||
char buff[LUA_IDSIZE];
|
||||
if (src)
|
||||
luaO_chunkid(buff, getstr(src), tsslen(src));
|
||||
else { /* no source available; use "?" instead */
|
||||
buff[0] = '?'; buff[1] = '\0';
|
||||
}
|
||||
return luaO_pushfstring(L, "%s:%d: %s", buff, line, msg);
|
||||
}
|
||||
|
||||
|
||||
l_noret luaG_errormsg (lua_State *L) {
|
||||
if (L->errfunc != 0) { /* is there an error handling function? */
|
||||
StkId errfunc = restorestack(L, L->errfunc);
|
||||
lua_assert(ttisfunction(s2v(errfunc)));
|
||||
setobjs2s(L, L->top.p, L->top.p - 1); /* move argument */
|
||||
setobjs2s(L, L->top.p - 1, errfunc); /* push function */
|
||||
L->top.p++; /* assume EXTRA_STACK */
|
||||
luaD_callnoyield(L, L->top.p - 2, 1); /* call it */
|
||||
}
|
||||
luaD_throw(L, LUA_ERRRUN);
|
||||
}
|
||||
|
||||
|
||||
l_noret luaG_runerror (lua_State *L, const char *fmt, ...) {
|
||||
CallInfo *ci = L->ci;
|
||||
const char *msg;
|
||||
va_list argp;
|
||||
luaC_checkGC(L); /* error message uses memory */
|
||||
va_start(argp, fmt);
|
||||
msg = luaO_pushvfstring(L, fmt, argp); /* format message */
|
||||
va_end(argp);
|
||||
if (isLua(ci)) { /* if Lua function, add source:line information */
|
||||
luaG_addinfo(L, msg, ci_func(ci)->p->source, getcurrentline(ci));
|
||||
setobjs2s(L, L->top.p - 2, L->top.p - 1); /* remove 'msg' */
|
||||
L->top.p--;
|
||||
}
|
||||
luaG_errormsg(L);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Check whether new instruction 'newpc' is in a different line from
|
||||
** previous instruction 'oldpc'. More often than not, 'newpc' is only
|
||||
** one or a few instructions after 'oldpc' (it must be after, see
|
||||
** caller), so try to avoid calling 'luaG_getfuncline'. If they are
|
||||
** too far apart, there is a good chance of a ABSLINEINFO in the way,
|
||||
** so it goes directly to 'luaG_getfuncline'.
|
||||
*/
|
||||
static int changedline (const Proto *p, int oldpc, int newpc) {
|
||||
if (p->lineinfo == NULL) /* no debug information? */
|
||||
return 0;
|
||||
if (newpc - oldpc < MAXIWTHABS / 2) { /* not too far apart? */
|
||||
int delta = 0; /* line difference */
|
||||
int pc = oldpc;
|
||||
for (;;) {
|
||||
int lineinfo = p->lineinfo[++pc];
|
||||
if (lineinfo == ABSLINEINFO)
|
||||
break; /* cannot compute delta; fall through */
|
||||
delta += lineinfo;
|
||||
if (pc == newpc)
|
||||
return (delta != 0); /* delta computed successfully */
|
||||
}
|
||||
}
|
||||
/* either instructions are too far apart or there is an absolute line
|
||||
info in the way; compute line difference explicitly */
|
||||
return (luaG_getfuncline(p, oldpc) != luaG_getfuncline(p, newpc));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Traces Lua calls. If code is running the first instruction of a function,
|
||||
** and function is not vararg, and it is not coming from an yield,
|
||||
** calls 'luaD_hookcall'. (Vararg functions will call 'luaD_hookcall'
|
||||
** after adjusting its variable arguments; otherwise, they could call
|
||||
** a line/count hook before the call hook. Functions coming from
|
||||
** an yield already called 'luaD_hookcall' before yielding.)
|
||||
*/
|
||||
int luaG_tracecall (lua_State *L) {
|
||||
CallInfo *ci = L->ci;
|
||||
Proto *p = ci_func(ci)->p;
|
||||
ci->u.l.trap = 1; /* ensure hooks will be checked */
|
||||
if (ci->u.l.savedpc == p->code) { /* first instruction (not resuming)? */
|
||||
if (p->is_vararg)
|
||||
return 0; /* hooks will start at VARARGPREP instruction */
|
||||
else if (!(ci->callstatus & CIST_HOOKYIELD)) /* not yieded? */
|
||||
luaD_hookcall(L, ci); /* check 'call' hook */
|
||||
}
|
||||
return 1; /* keep 'trap' on */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Traces the execution of a Lua function. Called before the execution
|
||||
** of each opcode, when debug is on. 'L->oldpc' stores the last
|
||||
** instruction traced, to detect line changes. When entering a new
|
||||
** function, 'npci' will be zero and will test as a new line whatever
|
||||
** the value of 'oldpc'. Some exceptional conditions may return to
|
||||
** a function without setting 'oldpc'. In that case, 'oldpc' may be
|
||||
** invalid; if so, use zero as a valid value. (A wrong but valid 'oldpc'
|
||||
** at most causes an extra call to a line hook.)
|
||||
** This function is not "Protected" when called, so it should correct
|
||||
** 'L->top.p' before calling anything that can run the GC.
|
||||
*/
|
||||
int luaG_traceexec (lua_State *L, const Instruction *pc) {
|
||||
CallInfo *ci = L->ci;
|
||||
lu_byte mask = L->hookmask;
|
||||
const Proto *p = ci_func(ci)->p;
|
||||
int counthook;
|
||||
if (!(mask & (LUA_MASKLINE | LUA_MASKCOUNT))) { /* no hooks? */
|
||||
ci->u.l.trap = 0; /* don't need to stop again */
|
||||
return 0; /* turn off 'trap' */
|
||||
}
|
||||
pc++; /* reference is always next instruction */
|
||||
ci->u.l.savedpc = pc; /* save 'pc' */
|
||||
counthook = (mask & LUA_MASKCOUNT) && (--L->hookcount == 0);
|
||||
if (counthook)
|
||||
resethookcount(L); /* reset count */
|
||||
else if (!(mask & LUA_MASKLINE))
|
||||
return 1; /* no line hook and count != 0; nothing to be done now */
|
||||
if (ci->callstatus & CIST_HOOKYIELD) { /* hook yielded last time? */
|
||||
ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */
|
||||
return 1; /* do not call hook again (VM yielded, so it did not move) */
|
||||
}
|
||||
if (!isIT(*(ci->u.l.savedpc - 1))) /* top not being used? */
|
||||
L->top.p = ci->top.p; /* correct top */
|
||||
if (counthook)
|
||||
luaD_hook(L, LUA_HOOKCOUNT, -1, 0, 0); /* call count hook */
|
||||
if (mask & LUA_MASKLINE) {
|
||||
/* 'L->oldpc' may be invalid; use zero in this case */
|
||||
int oldpc = (L->oldpc < p->sizecode) ? L->oldpc : 0;
|
||||
int npci = pcRel(pc, p);
|
||||
if (npci <= oldpc || /* call hook when jump back (loop), */
|
||||
changedline(p, oldpc, npci)) { /* or when enter new line */
|
||||
int newline = luaG_getfuncline(p, npci);
|
||||
luaD_hook(L, LUA_HOOKLINE, newline, 0, 0); /* call line hook */
|
||||
}
|
||||
L->oldpc = npci; /* 'pc' of last call to line hook */
|
||||
}
|
||||
if (L->status == LUA_YIELD) { /* did hook yield? */
|
||||
if (counthook)
|
||||
L->hookcount = 1; /* undo decrement to zero */
|
||||
ci->callstatus |= CIST_HOOKYIELD; /* mark that it yielded */
|
||||
luaD_throw(L, LUA_YIELD);
|
||||
}
|
||||
return 1; /* keep 'trap' on */
|
||||
}
|
||||
|
||||
64
src/lua/lua-5.4.8/src/ldebug.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
** $Id: ldebug.h $
|
||||
** Auxiliary functions from Debug Interface module
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#ifndef ldebug_h
|
||||
#define ldebug_h
|
||||
|
||||
|
||||
#include "lstate.h"
|
||||
|
||||
|
||||
#define pcRel(pc, p) (cast_int((pc) - (p)->code) - 1)
|
||||
|
||||
|
||||
/* Active Lua function (given call info) */
|
||||
#define ci_func(ci) (clLvalue(s2v((ci)->func.p)))
|
||||
|
||||
|
||||
#define resethookcount(L) (L->hookcount = L->basehookcount)
|
||||
|
||||
/*
|
||||
** mark for entries in 'lineinfo' array that has absolute information in
|
||||
** 'abslineinfo' array
|
||||
*/
|
||||
#define ABSLINEINFO (-0x80)
|
||||
|
||||
|
||||
/*
|
||||
** MAXimum number of successive Instructions WiTHout ABSolute line
|
||||
** information. (A power of two allows fast divisions.)
|
||||
*/
|
||||
#if !defined(MAXIWTHABS)
|
||||
#define MAXIWTHABS 128
|
||||
#endif
|
||||
|
||||
|
||||
LUAI_FUNC int luaG_getfuncline (const Proto *f, int pc);
|
||||
LUAI_FUNC const char *luaG_findlocal (lua_State *L, CallInfo *ci, int n,
|
||||
StkId *pos);
|
||||
LUAI_FUNC l_noret luaG_typeerror (lua_State *L, const TValue *o,
|
||||
const char *opname);
|
||||
LUAI_FUNC l_noret luaG_callerror (lua_State *L, const TValue *o);
|
||||
LUAI_FUNC l_noret luaG_forerror (lua_State *L, const TValue *o,
|
||||
const char *what);
|
||||
LUAI_FUNC l_noret luaG_concaterror (lua_State *L, const TValue *p1,
|
||||
const TValue *p2);
|
||||
LUAI_FUNC l_noret luaG_opinterror (lua_State *L, const TValue *p1,
|
||||
const TValue *p2,
|
||||
const char *msg);
|
||||
LUAI_FUNC l_noret luaG_tointerror (lua_State *L, const TValue *p1,
|
||||
const TValue *p2);
|
||||
LUAI_FUNC l_noret luaG_ordererror (lua_State *L, const TValue *p1,
|
||||
const TValue *p2);
|
||||
LUAI_FUNC l_noret luaG_runerror (lua_State *L, const char *fmt, ...);
|
||||
LUAI_FUNC const char *luaG_addinfo (lua_State *L, const char *msg,
|
||||
TString *src, int line);
|
||||
LUAI_FUNC l_noret luaG_errormsg (lua_State *L);
|
||||
LUAI_FUNC int luaG_traceexec (lua_State *L, const Instruction *pc);
|
||||
LUAI_FUNC int luaG_tracecall (lua_State *L);
|
||||
|
||||
|
||||
#endif
|
||||
1035
src/lua/lua-5.4.8/src/ldo.c
Normal file
88
src/lua/lua-5.4.8/src/ldo.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
** $Id: ldo.h $
|
||||
** Stack and Call structure of Lua
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#ifndef ldo_h
|
||||
#define ldo_h
|
||||
|
||||
|
||||
#include "llimits.h"
|
||||
#include "lobject.h"
|
||||
#include "lstate.h"
|
||||
#include "lzio.h"
|
||||
|
||||
|
||||
/*
|
||||
** Macro to check stack size and grow stack if needed. Parameters
|
||||
** 'pre'/'pos' allow the macro to preserve a pointer into the
|
||||
** stack across reallocations, doing the work only when needed.
|
||||
** It also allows the running of one GC step when the stack is
|
||||
** reallocated.
|
||||
** 'condmovestack' is used in heavy tests to force a stack reallocation
|
||||
** at every check.
|
||||
*/
|
||||
#define luaD_checkstackaux(L,n,pre,pos) \
|
||||
if (l_unlikely(L->stack_last.p - L->top.p <= (n))) \
|
||||
{ pre; luaD_growstack(L, n, 1); pos; } \
|
||||
else { condmovestack(L,pre,pos); }
|
||||
|
||||
/* In general, 'pre'/'pos' are empty (nothing to save) */
|
||||
#define luaD_checkstack(L,n) luaD_checkstackaux(L,n,(void)0,(void)0)
|
||||
|
||||
|
||||
|
||||
#define savestack(L,pt) (cast_charp(pt) - cast_charp(L->stack.p))
|
||||
#define restorestack(L,n) cast(StkId, cast_charp(L->stack.p) + (n))
|
||||
|
||||
|
||||
/* macro to check stack size, preserving 'p' */
|
||||
#define checkstackp(L,n,p) \
|
||||
luaD_checkstackaux(L, n, \
|
||||
ptrdiff_t t__ = savestack(L, p), /* save 'p' */ \
|
||||
p = restorestack(L, t__)) /* 'pos' part: restore 'p' */
|
||||
|
||||
|
||||
/* macro to check stack size and GC, preserving 'p' */
|
||||
#define checkstackGCp(L,n,p) \
|
||||
luaD_checkstackaux(L, n, \
|
||||
ptrdiff_t t__ = savestack(L, p); /* save 'p' */ \
|
||||
luaC_checkGC(L), /* stack grow uses memory */ \
|
||||
p = restorestack(L, t__)) /* 'pos' part: restore 'p' */
|
||||
|
||||
|
||||
/* macro to check stack size and GC */
|
||||
#define checkstackGC(L,fsize) \
|
||||
luaD_checkstackaux(L, (fsize), luaC_checkGC(L), (void)0)
|
||||
|
||||
|
||||
/* type of protected functions, to be ran by 'runprotected' */
|
||||
typedef void (*Pfunc) (lua_State *L, void *ud);
|
||||
|
||||
LUAI_FUNC l_noret luaD_errerr (lua_State *L);
|
||||
LUAI_FUNC void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop);
|
||||
LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name,
|
||||
const char *mode);
|
||||
LUAI_FUNC void luaD_hook (lua_State *L, int event, int line,
|
||||
int fTransfer, int nTransfer);
|
||||
LUAI_FUNC void luaD_hookcall (lua_State *L, CallInfo *ci);
|
||||
LUAI_FUNC int luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func,
|
||||
int narg1, int delta);
|
||||
LUAI_FUNC CallInfo *luaD_precall (lua_State *L, StkId func, int nResults);
|
||||
LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults);
|
||||
LUAI_FUNC void luaD_callnoyield (lua_State *L, StkId func, int nResults);
|
||||
LUAI_FUNC int luaD_closeprotected (lua_State *L, ptrdiff_t level, int status);
|
||||
LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u,
|
||||
ptrdiff_t oldtop, ptrdiff_t ef);
|
||||
LUAI_FUNC void luaD_poscall (lua_State *L, CallInfo *ci, int nres);
|
||||
LUAI_FUNC int luaD_reallocstack (lua_State *L, int newsize, int raiseerror);
|
||||
LUAI_FUNC int luaD_growstack (lua_State *L, int n, int raiseerror);
|
||||
LUAI_FUNC void luaD_shrinkstack (lua_State *L);
|
||||
LUAI_FUNC void luaD_inctop (lua_State *L);
|
||||
|
||||
LUAI_FUNC l_noret luaD_throw (lua_State *L, int errcode);
|
||||
LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud);
|
||||
|
||||
#endif
|
||||
|
||||